public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
* [PATCH 0/1] Update bitbake to version 1.50.4
@ 2022-02-01 11:42 Uladzimir Bely
  2022-02-01 11:42 ` [PATCH 1/1] bitbake: Update to 1.50.4 release Uladzimir Bely
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Uladzimir Bely @ 2022-02-01 11:42 UTC (permalink / raw)
  To: isar-users

Bitbake in Isar didn't get updates for almost 1.5 years. At the same time
the version we use have at least one annoying bug, when messages in log
files got duplicated if "--verbose" option is used and error happens.

This was fixed in upstream revision 69c622b744d9, few commits before the
tag 1.50.4.

Also, there is 1.52 branch exists (latest tag 1.52.1), but it seems to be
incompatible with Isar.

Uladzimir Bely (1):
  bitbake: Update to 1.50.4 release

 bitbake/.gitignore                            |    1 +
 bitbake/README                                |    2 +-
 bitbake/bin/bitbake                           |    2 +-
 bitbake/bin/bitbake-hashclient                |    3 -
 bitbake/bin/bitbake-hashserv                  |   10 +-
 bitbake/bin/bitbake-layers                    |    2 -
 bitbake/bin/bitbake-selftest                  |    2 +
 bitbake/bin/bitbake-server                    |   54 +
 bitbake/bin/bitbake-worker                    |   44 +-
 bitbake/bin/bitdoc                            |  519 ---
 bitbake/contrib/bbparse-torture.py            |   89 +
 bitbake/contrib/hashserv/Dockerfile           |   19 +
 bitbake/contrib/vim/LICENSE.txt               |   18 +
 bitbake/contrib/vim/ftdetect/bitbake.vim      |    4 +-
 bitbake/contrib/vim/ftplugin/bitbake.vim      |   15 +-
 bitbake/contrib/vim/plugin/newbb.vim          |   14 +-
 bitbake/contrib/vim/plugin/newbbappend.vim    |   46 +
 bitbake/contrib/vim/syntax/bitbake.vim        |   16 +-
 bitbake/doc/.gitignore                        |    1 +
 bitbake/doc/Makefile                          |  108 +-
 bitbake/doc/README                            |   50 +-
 bitbake/doc/_templates/breadcrumbs.html       |   14 +
 bitbake/doc/_templates/layout.html            |    7 +
 .../bitbake-user-manual-customization.xsl     |   29 -
 .../bitbake-user-manual-execution.rst         |  734 +++++
 .../bitbake-user-manual-execution.xml         | 1029 ------
 .../bitbake-user-manual-fetching.rst          |  689 ++++
 .../bitbake-user-manual-fetching.xml          |  868 -----
 .../bitbake-user-manual-hello.rst             |  415 +++
 .../bitbake-user-manual-hello.xml             |  513 ---
 .../bitbake-user-manual-intro.rst             |  651 ++++
 .../bitbake-user-manual-intro.xml             |  891 -----
 .../bitbake-user-manual-metadata.rst          | 1980 ++++++++++++
 .../bitbake-user-manual-metadata.xml          | 2862 -----------------
 .../bitbake-user-manual-ref-variables.rst     | 1405 ++++++++
 .../bitbake-user-manual-ref-variables.xml     | 2476 --------------
 .../bitbake-user-manual-style.css             |  984 ------
 .../bitbake-user-manual.xml                   |   88 -
 bitbake/doc/bitbake-user-manual/html.css      |  281 --
 bitbake/doc/conf.py                           |  101 +
 bitbake/doc/genindex.rst                      |    3 +
 bitbake/doc/index.rst                         |   38 +
 bitbake/doc/poky.ent                          |   51 -
 bitbake/doc/releases.rst                      |  130 +
 bitbake/doc/sphinx-static/switchers.js        |  233 ++
 bitbake/doc/sphinx-static/theme_overrides.css |  162 +
 bitbake/doc/template/Vera.xml                 |    1 -
 bitbake/doc/template/VeraMoBd.xml             |    1 -
 bitbake/doc/template/VeraMono.xml             |    1 -
 bitbake/doc/template/component.title.xsl      |   39 -
 bitbake/doc/template/db-pdf.xsl               |   64 -
 bitbake/doc/template/division.title.xsl       |   25 -
 bitbake/doc/template/fop-config.xml           |   58 -
 .../doc/template/formal.object.heading.xsl    |   21 -
 bitbake/doc/template/gloss-permalinks.xsl     |   14 -
 bitbake/doc/template/permalinks.xsl           |   25 -
 bitbake/doc/template/section.title.xsl        |   55 -
 bitbake/doc/template/titlepage.templates.xml  | 1259 --------
 bitbake/doc/tools/docbook-to-pdf              |   51 -
 bitbake/lib/bb/COW.py                         |  150 +-
 bitbake/lib/bb/__init__.py                    |   71 +-
 bitbake/lib/bb/build.py                       |  174 +-
 bitbake/lib/bb/cache.py                       |  249 +-
 bitbake/lib/bb/codeparser.py                  |    6 +-
 bitbake/lib/bb/command.py                     |   71 +-
 bitbake/lib/bb/compat.py                      |   10 -
 bitbake/lib/bb/cooker.py                      |  433 ++-
 bitbake/lib/bb/cookerdata.py                  |   74 +-
 bitbake/lib/bb/daemonize.py                   |    2 +
 bitbake/lib/bb/data.py                        |    6 +
 bitbake/lib/bb/data_smart.py                  |   20 +-
 bitbake/lib/bb/event.py                       |   61 +-
 bitbake/lib/bb/fetch2/__init__.py             |   99 +-
 bitbake/lib/bb/fetch2/az.py                   |   93 +
 bitbake/lib/bb/fetch2/bzr.py                  |    8 +-
 bitbake/lib/bb/fetch2/clearcase.py            |    2 +-
 bitbake/lib/bb/fetch2/cvs.py                  |   24 +-
 bitbake/lib/bb/fetch2/git.py                  |  106 +-
 bitbake/lib/bb/fetch2/gitsm.py                |   68 +-
 bitbake/lib/bb/fetch2/hg.py                   |   16 +-
 bitbake/lib/bb/fetch2/local.py                |   19 +-
 bitbake/lib/bb/fetch2/npmsw.py                |    4 +
 bitbake/lib/bb/fetch2/osc.py                  |    9 +-
 bitbake/lib/bb/fetch2/perforce.py             |   94 +-
 bitbake/lib/bb/fetch2/repo.py                 |    2 +-
 bitbake/lib/bb/fetch2/ssh.py                  |    7 +-
 bitbake/lib/bb/fetch2/svn.py                  |    8 +-
 bitbake/lib/bb/fetch2/wget.py                 |   32 +-
 bitbake/lib/bb/main.py                        |  355 +-
 bitbake/lib/bb/monitordisk.py                 |    4 +-
 bitbake/lib/bb/msg.py                         |    9 +-
 bitbake/lib/bb/namedtuple_with_abc.py         |   14 +-
 bitbake/lib/bb/parse/__init__.py              |    2 +-
 bitbake/lib/bb/parse/ast.py                   |   21 +-
 bitbake/lib/bb/parse/parse_py/BBHandler.py    |   15 +-
 bitbake/lib/bb/parse/parse_py/ConfHandler.py  |    4 +-
 bitbake/lib/bb/persist_data.py                |   10 +-
 bitbake/lib/bb/process.py                     |    7 +-
 bitbake/lib/bb/progress.py                    |   60 +-
 bitbake/lib/bb/providers.py                   |  108 +-
 bitbake/lib/bb/runqueue.py                    |  337 +-
 bitbake/lib/bb/server/process.py              |  273 +-
 bitbake/lib/bb/siggen.py                      |  125 +-
 bitbake/lib/bb/taskdata.py                    |   51 +-
 bitbake/lib/bb/tests/codeparser.py            |    4 +-
 bitbake/lib/bb/tests/color.py                 |   95 +
 bitbake/lib/bb/tests/cooker.py                |    2 +-
 bitbake/lib/bb/tests/cow.py                   |  218 +-
 bitbake/lib/bb/tests/data.py                  |    1 +
 bitbake/lib/bb/tests/event.py                 |   17 +-
 .../linux/utils/util-linux/v2.23/index.html   |   90 +-
 .../linux/utils/util-linux/v2.24/index.html   |   86 +-
 .../linux/utils/util-linux/v2.25/index.html   |   92 +-
 .../linux/utils/util-linux/v2.26/index.html   |   84 +-
 .../linux/utils/util-linux/v2.27/index.html   |   70 +-
 .../linux/utils/util-linux/v2.28/index.html   |   84 +-
 .../linux/utils/util-linux/v2.29/index.html   |   84 +-
 .../linux/utils/util-linux/v2.30/index.html   |   84 +-
 .../linux/utils/util-linux/v2.31/index.html   |   70 +-
 .../linux/utils/util-linux/v2.32/index.html   |   70 +-
 .../linux/utils/util-linux/v2.33/index.html   |   84 +-
 .../linux/utils/util-linux/v2.34/index.html   |   56 +-
 .../linux/utils/util-linux/v2.35/index.html   |   36 +-
 .../fetch-testdata/releases/eglibc/index.html |   42 +-
 .../releases/gnu-config/index.html            |   18 +-
 bitbake/lib/bb/tests/fetch.py                 |  237 +-
 bitbake/lib/bb/tests/parse.py                 |    6 +-
 .../bb/tests/runqueue-tests/conf/bitbake.conf |    3 +-
 .../runqueue-tests/conf/multiconfig/mc-1.conf |    2 +
 .../runqueue-tests/conf/multiconfig/mc1.conf  |    1 -
 .../runqueue-tests/conf/multiconfig/mc2.conf  |    1 -
 .../runqueue-tests/conf/multiconfig/mc_2.conf |    2 +
 .../lib/bb/tests/runqueue-tests/recipes/f1.bb |    1 +
 .../recipes/fails-mc/fails-mc1.bb             |    5 +
 .../recipes/fails-mc/fails-mc2.bb             |    4 +
 bitbake/lib/bb/tests/runqueue.py              |   59 +-
 bitbake/lib/bb/tests/siggen.py                |   91 +
 bitbake/lib/bb/tinfoil.py                     |   75 +-
 bitbake/lib/bb/ui/buildinfohelper.py          |   10 +-
 bitbake/lib/bb/ui/knotty.py                   |   27 +-
 bitbake/lib/bb/ui/ncurses.py                  |    2 +
 bitbake/lib/bb/ui/taskexp.py                  |    7 +-
 bitbake/lib/bb/ui/toasterui.py                |    6 +-
 bitbake/lib/bb/ui/uievent.py                  |    6 +-
 bitbake/lib/bb/ui/uihelper.py                 |    4 +-
 bitbake/lib/bb/utils.py                       |  118 +-
 bitbake/lib/bblayers/action.py                |   26 +-
 bitbake/lib/bblayers/layerindex.py            |    2 +-
 bitbake/lib/bblayers/query.py                 |   18 +-
 bitbake/lib/bs4/testing.py                    |    6 +-
 bitbake/lib/hashserv/__init__.py              |   52 +-
 bitbake/lib/hashserv/client.py                |  258 +-
 bitbake/lib/hashserv/server.py                |  232 +-
 bitbake/lib/hashserv/tests.py                 |  223 +-
 bitbake/lib/layerindexlib/__init__.py         |   61 +-
 bitbake/lib/layerindexlib/cooker.py           |   11 +-
 bitbake/lib/layerindexlib/restapi.py          |   38 +-
 bitbake/lib/layerindexlib/tests/cooker.py     |    4 +-
 bitbake/lib/layerindexlib/tests/restapi.py    |   20 +-
 bitbake/lib/ply/lex.py                        |    6 +-
 bitbake/lib/ply/yacc.py                       |    2 +-
 bitbake/lib/toaster/orm/fixtures/oe-core.xml  |   12 +-
 bitbake/lib/toaster/orm/fixtures/poky.xml     |   18 +-
 .../orm/management/commands/lsupdates.py      |    2 +-
 .../tests/functional/functional_helpers.py    |    8 +-
 .../toaster/toastergui/templates/base.html    |    2 +-
 .../toastergui/templates/configvars.html      |    2 +-
 .../toaster/toastergui/templates/landing.html |    8 +-
 .../templates/landing_not_managed.html        |    2 +-
 .../toaster/toastergui/templates/project.html |    2 +-
 .../templates/project_specific.html           |    2 +-
 .../toastergui/templates/projectconf.html     |    8 +-
 .../toastermain/management/commands/perf.py   |   68 +-
 173 files changed, 11143 insertions(+), 14584 deletions(-)
 create mode 100755 bitbake/bin/bitbake-server
 delete mode 100755 bitbake/bin/bitdoc
 create mode 100755 bitbake/contrib/bbparse-torture.py
 create mode 100644 bitbake/contrib/hashserv/Dockerfile
 create mode 100644 bitbake/contrib/vim/LICENSE.txt
 mode change 100755 => 100644 bitbake/contrib/vim/plugin/newbb.vim
 create mode 100644 bitbake/contrib/vim/plugin/newbbappend.vim
 create mode 100644 bitbake/doc/.gitignore
 create mode 100644 bitbake/doc/_templates/breadcrumbs.html
 create mode 100644 bitbake/doc/_templates/layout.html
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-customization.xsl
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
 delete mode 100644 bitbake/doc/bitbake-user-manual/html.css
 create mode 100644 bitbake/doc/conf.py
 create mode 100644 bitbake/doc/genindex.rst
 create mode 100644 bitbake/doc/index.rst
 delete mode 100644 bitbake/doc/poky.ent
 create mode 100644 bitbake/doc/releases.rst
 create mode 100644 bitbake/doc/sphinx-static/switchers.js
 create mode 100644 bitbake/doc/sphinx-static/theme_overrides.css
 delete mode 100644 bitbake/doc/template/Vera.xml
 delete mode 100644 bitbake/doc/template/VeraMoBd.xml
 delete mode 100644 bitbake/doc/template/VeraMono.xml
 delete mode 100644 bitbake/doc/template/component.title.xsl
 delete mode 100644 bitbake/doc/template/db-pdf.xsl
 delete mode 100644 bitbake/doc/template/division.title.xsl
 delete mode 100644 bitbake/doc/template/fop-config.xml
 delete mode 100644 bitbake/doc/template/formal.object.heading.xsl
 delete mode 100644 bitbake/doc/template/gloss-permalinks.xsl
 delete mode 100644 bitbake/doc/template/permalinks.xsl
 delete mode 100644 bitbake/doc/template/section.title.xsl
 delete mode 100644 bitbake/doc/template/titlepage.templates.xml
 delete mode 100755 bitbake/doc/tools/docbook-to-pdf
 delete mode 100644 bitbake/lib/bb/compat.py
 create mode 100644 bitbake/lib/bb/fetch2/az.py
 create mode 100644 bitbake/lib/bb/tests/color.py
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc-1.conf
 delete mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf
 delete mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc_2.conf
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/f1.bb
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc1.bb
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc2.bb
 create mode 100644 bitbake/lib/bb/tests/siggen.py

-- 
2.20.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/1] bitbake: Update to 1.50.4 release
  2022-02-01 11:42 [PATCH 0/1] Update bitbake to version 1.50.4 Uladzimir Bely
@ 2022-02-01 11:42 ` Uladzimir Bely
  2022-02-02  6:25 ` [PATCH 0/1] Update bitbake to version 1.50.4 Schmidt, Adriaan
  2022-03-25  6:31 ` Anton Mikanovich
  2 siblings, 0 replies; 11+ messages in thread
From: Uladzimir Bely @ 2022-02-01 11:42 UTC (permalink / raw)
  To: isar-users

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 1539204 bytes --]

Update bitbake to the latest release in 1.50 branch. This release is
tagged to the commit ID 0fe1a9e2d2e33f80d807cefc7a23df4a5f760c74
in the bitbake upstream.

The version in bin/bitbake is shown as 1.50.0.

Signed-off-by: Uladzimir Bely <ubely@ilbers.de>
---
 bitbake/.gitignore                            |    1 +
 bitbake/README                                |    2 +-
 bitbake/bin/bitbake                           |    2 +-
 bitbake/bin/bitbake-hashclient                |    3 -
 bitbake/bin/bitbake-hashserv                  |   10 +-
 bitbake/bin/bitbake-layers                    |    2 -
 bitbake/bin/bitbake-selftest                  |    2 +
 bitbake/bin/bitbake-server                    |   54 +
 bitbake/bin/bitbake-worker                    |   44 +-
 bitbake/bin/bitdoc                            |  519 ---
 bitbake/contrib/bbparse-torture.py            |   89 +
 bitbake/contrib/hashserv/Dockerfile           |   19 +
 bitbake/contrib/vim/LICENSE.txt               |   18 +
 bitbake/contrib/vim/ftdetect/bitbake.vim      |    4 +-
 bitbake/contrib/vim/ftplugin/bitbake.vim      |   15 +-
 bitbake/contrib/vim/plugin/newbb.vim          |   14 +-
 bitbake/contrib/vim/plugin/newbbappend.vim    |   46 +
 bitbake/contrib/vim/syntax/bitbake.vim        |   16 +-
 bitbake/doc/.gitignore                        |    1 +
 bitbake/doc/Makefile                          |  108 +-
 bitbake/doc/README                            |   50 +-
 bitbake/doc/_templates/breadcrumbs.html       |   14 +
 bitbake/doc/_templates/layout.html            |    7 +
 .../bitbake-user-manual-customization.xsl     |   29 -
 .../bitbake-user-manual-execution.rst         |  734 +++++
 .../bitbake-user-manual-execution.xml         | 1029 ------
 .../bitbake-user-manual-fetching.rst          |  689 ++++
 .../bitbake-user-manual-fetching.xml          |  868 -----
 .../bitbake-user-manual-hello.rst             |  415 +++
 .../bitbake-user-manual-hello.xml             |  513 ---
 .../bitbake-user-manual-intro.rst             |  651 ++++
 .../bitbake-user-manual-intro.xml             |  891 -----
 .../bitbake-user-manual-metadata.rst          | 1980 ++++++++++++
 .../bitbake-user-manual-metadata.xml          | 2862 -----------------
 .../bitbake-user-manual-ref-variables.rst     | 1405 ++++++++
 .../bitbake-user-manual-ref-variables.xml     | 2476 --------------
 .../bitbake-user-manual-style.css             |  984 ------
 .../bitbake-user-manual.xml                   |   88 -
 bitbake/doc/bitbake-user-manual/html.css      |  281 --
 bitbake/doc/conf.py                           |  101 +
 bitbake/doc/genindex.rst                      |    3 +
 bitbake/doc/index.rst                         |   38 +
 bitbake/doc/poky.ent                          |   51 -
 bitbake/doc/releases.rst                      |  130 +
 bitbake/doc/sphinx-static/switchers.js        |  233 ++
 bitbake/doc/sphinx-static/theme_overrides.css |  162 +
 bitbake/doc/template/Vera.xml                 |    1 -
 bitbake/doc/template/VeraMoBd.xml             |    1 -
 bitbake/doc/template/VeraMono.xml             |    1 -
 bitbake/doc/template/component.title.xsl      |   39 -
 bitbake/doc/template/db-pdf.xsl               |   64 -
 bitbake/doc/template/division.title.xsl       |   25 -
 bitbake/doc/template/fop-config.xml           |   58 -
 .../doc/template/formal.object.heading.xsl    |   21 -
 bitbake/doc/template/gloss-permalinks.xsl     |   14 -
 bitbake/doc/template/permalinks.xsl           |   25 -
 bitbake/doc/template/section.title.xsl        |   55 -
 bitbake/doc/template/titlepage.templates.xml  | 1259 --------
 bitbake/doc/tools/docbook-to-pdf              |   51 -
 bitbake/lib/bb/COW.py                         |  150 +-
 bitbake/lib/bb/__init__.py                    |   71 +-
 bitbake/lib/bb/build.py                       |  174 +-
 bitbake/lib/bb/cache.py                       |  249 +-
 bitbake/lib/bb/codeparser.py                  |    6 +-
 bitbake/lib/bb/command.py                     |   71 +-
 bitbake/lib/bb/compat.py                      |   10 -
 bitbake/lib/bb/cooker.py                      |  433 ++-
 bitbake/lib/bb/cookerdata.py                  |   74 +-
 bitbake/lib/bb/daemonize.py                   |    2 +
 bitbake/lib/bb/data.py                        |    6 +
 bitbake/lib/bb/data_smart.py                  |   20 +-
 bitbake/lib/bb/event.py                       |   61 +-
 bitbake/lib/bb/fetch2/__init__.py             |   99 +-
 bitbake/lib/bb/fetch2/az.py                   |   93 +
 bitbake/lib/bb/fetch2/bzr.py                  |    8 +-
 bitbake/lib/bb/fetch2/clearcase.py            |    2 +-
 bitbake/lib/bb/fetch2/cvs.py                  |   24 +-
 bitbake/lib/bb/fetch2/git.py                  |  106 +-
 bitbake/lib/bb/fetch2/gitsm.py                |   68 +-
 bitbake/lib/bb/fetch2/hg.py                   |   16 +-
 bitbake/lib/bb/fetch2/local.py                |   19 +-
 bitbake/lib/bb/fetch2/npmsw.py                |    4 +
 bitbake/lib/bb/fetch2/osc.py                  |    9 +-
 bitbake/lib/bb/fetch2/perforce.py             |   94 +-
 bitbake/lib/bb/fetch2/repo.py                 |    2 +-
 bitbake/lib/bb/fetch2/ssh.py                  |    7 +-
 bitbake/lib/bb/fetch2/svn.py                  |    8 +-
 bitbake/lib/bb/fetch2/wget.py                 |   32 +-
 bitbake/lib/bb/main.py                        |  355 +-
 bitbake/lib/bb/monitordisk.py                 |    4 +-
 bitbake/lib/bb/msg.py                         |    9 +-
 bitbake/lib/bb/namedtuple_with_abc.py         |   14 +-
 bitbake/lib/bb/parse/__init__.py              |    2 +-
 bitbake/lib/bb/parse/ast.py                   |   21 +-
 bitbake/lib/bb/parse/parse_py/BBHandler.py    |   15 +-
 bitbake/lib/bb/parse/parse_py/ConfHandler.py  |    4 +-
 bitbake/lib/bb/persist_data.py                |   10 +-
 bitbake/lib/bb/process.py                     |    7 +-
 bitbake/lib/bb/progress.py                    |   60 +-
 bitbake/lib/bb/providers.py                   |  108 +-
 bitbake/lib/bb/runqueue.py                    |  337 +-
 bitbake/lib/bb/server/process.py              |  273 +-
 bitbake/lib/bb/siggen.py                      |  125 +-
 bitbake/lib/bb/taskdata.py                    |   51 +-
 bitbake/lib/bb/tests/codeparser.py            |    4 +-
 bitbake/lib/bb/tests/color.py                 |   95 +
 bitbake/lib/bb/tests/cooker.py                |    2 +-
 bitbake/lib/bb/tests/cow.py                   |  218 +-
 bitbake/lib/bb/tests/data.py                  |    1 +
 bitbake/lib/bb/tests/event.py                 |   17 +-
 .../linux/utils/util-linux/v2.23/index.html   |   90 +-
 .../linux/utils/util-linux/v2.24/index.html   |   86 +-
 .../linux/utils/util-linux/v2.25/index.html   |   92 +-
 .../linux/utils/util-linux/v2.26/index.html   |   84 +-
 .../linux/utils/util-linux/v2.27/index.html   |   70 +-
 .../linux/utils/util-linux/v2.28/index.html   |   84 +-
 .../linux/utils/util-linux/v2.29/index.html   |   84 +-
 .../linux/utils/util-linux/v2.30/index.html   |   84 +-
 .../linux/utils/util-linux/v2.31/index.html   |   70 +-
 .../linux/utils/util-linux/v2.32/index.html   |   70 +-
 .../linux/utils/util-linux/v2.33/index.html   |   84 +-
 .../linux/utils/util-linux/v2.34/index.html   |   56 +-
 .../linux/utils/util-linux/v2.35/index.html   |   36 +-
 .../fetch-testdata/releases/eglibc/index.html |   42 +-
 .../releases/gnu-config/index.html            |   18 +-
 bitbake/lib/bb/tests/fetch.py                 |  237 +-
 bitbake/lib/bb/tests/parse.py                 |    6 +-
 .../bb/tests/runqueue-tests/conf/bitbake.conf |    3 +-
 .../runqueue-tests/conf/multiconfig/mc-1.conf |    2 +
 .../runqueue-tests/conf/multiconfig/mc1.conf  |    1 -
 .../runqueue-tests/conf/multiconfig/mc2.conf  |    1 -
 .../runqueue-tests/conf/multiconfig/mc_2.conf |    2 +
 .../lib/bb/tests/runqueue-tests/recipes/f1.bb |    1 +
 .../recipes/fails-mc/fails-mc1.bb             |    5 +
 .../recipes/fails-mc/fails-mc2.bb             |    4 +
 bitbake/lib/bb/tests/runqueue.py              |   59 +-
 bitbake/lib/bb/tests/siggen.py                |   91 +
 bitbake/lib/bb/tinfoil.py                     |   75 +-
 bitbake/lib/bb/ui/buildinfohelper.py          |   10 +-
 bitbake/lib/bb/ui/knotty.py                   |   27 +-
 bitbake/lib/bb/ui/ncurses.py                  |    2 +
 bitbake/lib/bb/ui/taskexp.py                  |    7 +-
 bitbake/lib/bb/ui/toasterui.py                |    6 +-
 bitbake/lib/bb/ui/uievent.py                  |    6 +-
 bitbake/lib/bb/ui/uihelper.py                 |    4 +-
 bitbake/lib/bb/utils.py                       |  118 +-
 bitbake/lib/bblayers/action.py                |   26 +-
 bitbake/lib/bblayers/layerindex.py            |    2 +-
 bitbake/lib/bblayers/query.py                 |   18 +-
 bitbake/lib/bs4/testing.py                    |    6 +-
 bitbake/lib/hashserv/__init__.py              |   52 +-
 bitbake/lib/hashserv/client.py                |  258 +-
 bitbake/lib/hashserv/server.py                |  232 +-
 bitbake/lib/hashserv/tests.py                 |  223 +-
 bitbake/lib/layerindexlib/__init__.py         |   61 +-
 bitbake/lib/layerindexlib/cooker.py           |   11 +-
 bitbake/lib/layerindexlib/restapi.py          |   38 +-
 bitbake/lib/layerindexlib/tests/cooker.py     |    4 +-
 bitbake/lib/layerindexlib/tests/restapi.py    |   20 +-
 bitbake/lib/ply/lex.py                        |    6 +-
 bitbake/lib/ply/yacc.py                       |    2 +-
 bitbake/lib/toaster/orm/fixtures/oe-core.xml  |   12 +-
 bitbake/lib/toaster/orm/fixtures/poky.xml     |   18 +-
 .../orm/management/commands/lsupdates.py      |    2 +-
 .../tests/functional/functional_helpers.py    |    8 +-
 .../toaster/toastergui/templates/base.html    |    2 +-
 .../toastergui/templates/configvars.html      |    2 +-
 .../toaster/toastergui/templates/landing.html |    8 +-
 .../templates/landing_not_managed.html        |    2 +-
 .../toaster/toastergui/templates/project.html |    2 +-
 .../templates/project_specific.html           |    2 +-
 .../toastergui/templates/projectconf.html     |    8 +-
 .../toastermain/management/commands/perf.py   |   68 +-
 173 files changed, 11143 insertions(+), 14584 deletions(-)
 create mode 100755 bitbake/bin/bitbake-server
 delete mode 100755 bitbake/bin/bitdoc
 create mode 100755 bitbake/contrib/bbparse-torture.py
 create mode 100644 bitbake/contrib/hashserv/Dockerfile
 create mode 100644 bitbake/contrib/vim/LICENSE.txt
 mode change 100755 => 100644 bitbake/contrib/vim/plugin/newbb.vim
 create mode 100644 bitbake/contrib/vim/plugin/newbbappend.vim
 create mode 100644 bitbake/doc/.gitignore
 create mode 100644 bitbake/doc/_templates/breadcrumbs.html
 create mode 100644 bitbake/doc/_templates/layout.html
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-customization.xsl
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
 create mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.rst
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
 delete mode 100644 bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
 delete mode 100644 bitbake/doc/bitbake-user-manual/html.css
 create mode 100644 bitbake/doc/conf.py
 create mode 100644 bitbake/doc/genindex.rst
 create mode 100644 bitbake/doc/index.rst
 delete mode 100644 bitbake/doc/poky.ent
 create mode 100644 bitbake/doc/releases.rst
 create mode 100644 bitbake/doc/sphinx-static/switchers.js
 create mode 100644 bitbake/doc/sphinx-static/theme_overrides.css
 delete mode 100644 bitbake/doc/template/Vera.xml
 delete mode 100644 bitbake/doc/template/VeraMoBd.xml
 delete mode 100644 bitbake/doc/template/VeraMono.xml
 delete mode 100644 bitbake/doc/template/component.title.xsl
 delete mode 100644 bitbake/doc/template/db-pdf.xsl
 delete mode 100644 bitbake/doc/template/division.title.xsl
 delete mode 100644 bitbake/doc/template/fop-config.xml
 delete mode 100644 bitbake/doc/template/formal.object.heading.xsl
 delete mode 100644 bitbake/doc/template/gloss-permalinks.xsl
 delete mode 100644 bitbake/doc/template/permalinks.xsl
 delete mode 100644 bitbake/doc/template/section.title.xsl
 delete mode 100644 bitbake/doc/template/titlepage.templates.xml
 delete mode 100755 bitbake/doc/tools/docbook-to-pdf
 delete mode 100644 bitbake/lib/bb/compat.py
 create mode 100644 bitbake/lib/bb/fetch2/az.py
 create mode 100644 bitbake/lib/bb/tests/color.py
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc-1.conf
 delete mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf
 delete mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc_2.conf
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/f1.bb
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc1.bb
 create mode 100644 bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc2.bb
 create mode 100644 bitbake/lib/bb/tests/siggen.py

diff --git a/bitbake/.gitignore b/bitbake/.gitignore
index 8ca4b5d1..fbf9eb20 100644
--- a/bitbake/.gitignore
+++ b/bitbake/.gitignore
@@ -15,3 +15,4 @@ doc/bitbake-user-manual/bitbake-user-manual.tgz
 lib/toaster/contrib/tts/backlog.txt
 lib/toaster/contrib/tts/log/*
 lib/toaster/contrib/tts/.cache/*
+lib/bb/tests/runqueue-tests/bitbake-cookerdaemon.log
diff --git a/bitbake/README b/bitbake/README
index 479c3765..96e6007e 100644
--- a/bitbake/README
+++ b/bitbake/README
@@ -11,7 +11,7 @@ For information about Bitbake, see the OpenEmbedded website:
 
 Bitbake plain documentation can be found under the doc directory or its integrated
 html version at the Yocto Project website:
-    http://yoctoproject.org/documentation
+    https://docs.yoctoproject.org
 
 Contributing
 ------------
diff --git a/bitbake/bin/bitbake b/bitbake/bin/bitbake
index 6c73710c..71275508 100755
--- a/bitbake/bin/bitbake
+++ b/bitbake/bin/bitbake
@@ -26,7 +26,7 @@ from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException
 if sys.getfilesystemencoding() != "utf-8":
     sys.exit("Please use a locale setting which supports UTF-8 (such as LANG=en_US.UTF-8).\nPython can't change the filesystem locale after loading so we need a UTF-8 when Python starts or things won't work.")
 
-__version__ = "1.46.0"
+__version__ = "1.50.0"
 
 if __name__ == "__main__":
     if __version__ != bb.__version__:
diff --git a/bitbake/bin/bitbake-hashclient b/bitbake/bin/bitbake-hashclient
index 29ab65f1..a8929021 100755
--- a/bitbake/bin/bitbake-hashclient
+++ b/bitbake/bin/bitbake-hashclient
@@ -151,9 +151,6 @@ def main():
     func = getattr(args, 'func', None)
     if func:
         client = hashserv.create_client(args.address)
-        # Try to establish a connection to the server now to detect failures
-        # early
-        client.connect()
 
         return func(args, client)
 
diff --git a/bitbake/bin/bitbake-hashserv b/bitbake/bin/bitbake-hashserv
index 1bc1f91f..153f65a3 100755
--- a/bitbake/bin/bitbake-hashserv
+++ b/bitbake/bin/bitbake-hashserv
@@ -30,9 +30,11 @@ def main():
                                                "--bind [::1]:8686"'''
                                      )
 
-    parser.add_argument('--bind', default=DEFAULT_BIND, help='Bind address (default "%(default)s")')
-    parser.add_argument('--database', default='./hashserv.db', help='Database file (default "%(default)s")')
-    parser.add_argument('--log', default='WARNING', help='Set logging level')
+    parser.add_argument('-b', '--bind', default=DEFAULT_BIND, help='Bind address (default "%(default)s")')
+    parser.add_argument('-d', '--database', default='./hashserv.db', help='Database file (default "%(default)s")')
+    parser.add_argument('-l', '--log', default='WARNING', help='Set logging level')
+    parser.add_argument('-u', '--upstream', help='Upstream hashserv to pull hashes from')
+    parser.add_argument('-r', '--read-only', action='store_true', help='Disallow write operations from clients')
 
     args = parser.parse_args()
 
@@ -47,7 +49,7 @@ def main():
     console.setLevel(level)
     logger.addHandler(console)
 
-    server = hashserv.create_server(args.bind, args.database)
+    server = hashserv.create_server(args.bind, args.database, upstream=args.upstream, read_only=args.read_only)
     server.serve_forever()
     return 0
 
diff --git a/bitbake/bin/bitbake-layers b/bitbake/bin/bitbake-layers
index 149f1b1a..ff085d67 100755
--- a/bitbake/bin/bitbake-layers
+++ b/bitbake/bin/bitbake-layers
@@ -14,7 +14,6 @@ import logging
 import os
 import sys
 import argparse
-import signal
 
 bindir = os.path.dirname(__file__)
 topdir = os.path.dirname(bindir)
@@ -26,7 +25,6 @@ import bb.msg
 logger = bb.msg.logger_create('bitbake-layers', sys.stdout)
 
 def main():
-    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
     parser = argparse.ArgumentParser(
         description="BitBake layers utility",
         epilog="Use %(prog)s <subcommand> --help to get help on a specific command",
diff --git a/bitbake/bin/bitbake-selftest b/bitbake/bin/bitbake-selftest
index 041a2719..6c073741 100755
--- a/bitbake/bin/bitbake-selftest
+++ b/bitbake/bin/bitbake-selftest
@@ -18,6 +18,7 @@ except RuntimeError as exc:
     sys.exit(str(exc))
 
 tests = ["bb.tests.codeparser",
+         "bb.tests.color",
          "bb.tests.cooker",
          "bb.tests.cow",
          "bb.tests.data",
@@ -26,6 +27,7 @@ tests = ["bb.tests.codeparser",
          "bb.tests.parse",
          "bb.tests.persist_data",
          "bb.tests.runqueue",
+         "bb.tests.siggen",
          "bb.tests.utils",
          "hashserv.tests",
          "layerindexlib.tests.layerindexobj",
diff --git a/bitbake/bin/bitbake-server b/bitbake/bin/bitbake-server
new file mode 100755
index 00000000..65796be7
--- /dev/null
+++ b/bitbake/bin/bitbake-server
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2020        Richard Purdie
+#
+
+import os
+import sys
+import warnings
+import logging
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
+
+if sys.getfilesystemencoding() != "utf-8":
+    sys.exit("Please use a locale setting which supports UTF-8 (such as LANG=en_US.UTF-8).\nPython can't change the filesystem locale after loading so we need a UTF-8 when Python starts or things won't work.")
+
+# Users shouldn't be running this code directly
+if len(sys.argv) != 10 or not sys.argv[1].startswith("decafbad"):
+    print("bitbake-server is meant for internal execution by bitbake itself, please don't use it standalone.")
+    sys.exit(1)
+
+import bb.server.process
+
+lockfd = int(sys.argv[2])
+readypipeinfd = int(sys.argv[3])
+logfile = sys.argv[4]
+lockname = sys.argv[5]
+sockname = sys.argv[6]
+timeout = float(sys.argv[7])
+xmlrpcinterface = (sys.argv[8], int(sys.argv[9]))
+if xmlrpcinterface[0] == "None":
+    xmlrpcinterface = (None, xmlrpcinterface[1])
+if timeout == "None":
+    timeout = None
+
+# Replace standard fds with our own
+with open('/dev/null', 'r') as si:
+    os.dup2(si.fileno(), sys.stdin.fileno())
+
+so = open(logfile, 'a+')
+os.dup2(so.fileno(), sys.stdout.fileno())
+os.dup2(so.fileno(), sys.stderr.fileno())
+
+# Have stdout and stderr be the same so log output matches chronologically
+# and there aren't two seperate buffers
+sys.stderr = sys.stdout
+
+logger = logging.getLogger("BitBake")
+# Ensure logging messages get sent to the UI as events
+handler = bb.event.LogHandler()
+logger.addHandler(handler)
+
+bb.server.process.execServer(lockfd, readypipeinfd, lockname, sockname, timeout, xmlrpcinterface)
+
diff --git a/bitbake/bin/bitbake-worker b/bitbake/bin/bitbake-worker
index 97cc0fd6..4318ce61 100755
--- a/bitbake/bin/bitbake-worker
+++ b/bitbake/bin/bitbake-worker
@@ -16,6 +16,8 @@ import signal
 import pickle
 import traceback
 import queue
+import shlex
+import subprocess
 from multiprocessing import Lock
 from threading import Thread
 
@@ -118,7 +120,9 @@ def worker_child_fire(event, d):
     data = b"<event>" + pickle.dumps(event) + b"</event>"
     try:
         worker_pipe_lock.acquire()
-        worker_pipe.write(data)
+        while(len(data)):
+            written = worker_pipe.write(data)
+            data = data[written:]
         worker_pipe_lock.release()
     except IOError:
         sigterm_handler(None, None)
@@ -143,21 +147,27 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, taskha
     # a fork() or exec*() activates PSEUDO...
 
     envbackup = {}
+    fakeroot = False
     fakeenv = {}
     umask = None
 
     taskdep = workerdata["taskdeps"][fn]
     if 'umask' in taskdep and taskname in taskdep['umask']:
+        umask = taskdep['umask'][taskname]
+    elif workerdata["umask"]:
+        umask = workerdata["umask"]
+    if umask:
         # umask might come in as a number or text string..
         try:
-             umask = int(taskdep['umask'][taskname],8)
+             umask = int(umask, 8)
         except TypeError:
-             umask = taskdep['umask'][taskname]
+             pass
 
     dry_run = cfg.dry_run or dry_run_exec
 
     # We can't use the fakeroot environment in a dry run as it possibly hasn't been built
     if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not dry_run:
+        fakeroot = True
         envvars = (workerdata["fakerootenv"][fn] or "").split()
         for key, value in (var.split('=') for var in envvars):
             envbackup[key] = os.environ.get(key)
@@ -167,7 +177,7 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, taskha
         fakedirs = (workerdata["fakerootdirs"][fn] or "").split()
         for p in fakedirs:
             bb.utils.mkdirhier(p)
-        logger.debug(2, 'Running %s:%s under fakeroot, fakedirs: %s' %
+        logger.debug2('Running %s:%s under fakeroot, fakedirs: %s' %
                         (fn, taskname, ', '.join(fakedirs)))
     else:
         envvars = (workerdata["fakerootnoenv"][fn] or "").split()
@@ -276,7 +286,13 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, taskha
             try:
                 if dry_run:
                     return 0
-                return bb.build.exec_task(fn, taskname, the_data, cfg.profile)
+                try:
+                    ret = bb.build.exec_task(fn, taskname, the_data, cfg.profile)
+                finally:
+                    if fakeroot:
+                        fakerootcmd = shlex.split(the_data.getVar("FAKEROOTCMD"))
+                        subprocess.run(fakerootcmd + ['-S'], check=True, stdout=subprocess.PIPE)
+                return ret
             except:
                 os._exit(1)
         if not profiling:
@@ -321,7 +337,9 @@ class runQueueWorkerPipe():
         end = len(self.queue)
         index = self.queue.find(b"</event>")
         while index != -1:
-            worker_fire_prepickled(self.queue[:index+8])
+            msg = self.queue[:index+8]
+            assert msg.startswith(b"<event>") and msg.count(b"<event>") == 1
+            worker_fire_prepickled(msg)
             self.queue = self.queue[index+8:]
             index = self.queue.find(b"</event>")
         return (end > start)
@@ -413,9 +431,9 @@ class BitbakeWorker(object):
 
     def handle_workerdata(self, data):
         self.workerdata = pickle.loads(data)
+        bb.build.verboseShellLogging = self.workerdata["build_verbose_shell"]
+        bb.build.verboseStdoutLogging = self.workerdata["build_verbose_stdout"]
         bb.msg.loggerDefaultLogLevel = self.workerdata["logdefaultlevel"]
-        bb.msg.loggerDefaultVerbose = self.workerdata["logdefaultverbose"]
-        bb.msg.loggerVerboseLogs = self.workerdata["logdefaultverboselogs"]
         bb.msg.loggerDefaultDomains = self.workerdata["logdefaultdomain"]
         for mc in self.databuilder.mcdata:
             self.databuilder.mcdata[mc].setVar("PRSERV_HOST", self.workerdata["prhost"])
@@ -505,9 +523,11 @@ except BaseException as e:
         import traceback
         sys.stderr.write(traceback.format_exc())
         sys.stderr.write(str(e))
+finally:
+    worker_thread_exit = True
+    worker_thread.join()
 
-worker_thread_exit = True
-worker_thread.join()
-
-workerlog_write("exitting")
+workerlog_write("exiting")
+if not normalexit:
+    sys.exit(1)
 sys.exit(0)
diff --git a/bitbake/bin/bitdoc b/bitbake/bin/bitdoc
deleted file mode 100755
index 9bd02be6..00000000
--- a/bitbake/bin/bitdoc
+++ /dev/null
@@ -1,519 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2005 Holger Hans Peter Freyther
-#
-# SPDX-License-Identifier: GPL-2.0-only
-#
-
-import optparse, os, sys
-
-# bitbake
-sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__), 'lib'))
-import bb
-import bb.parse
-from   string import split, join
-
-__version__ = "0.0.2"
-
-class HTMLFormatter:
-    """
-    Simple class to help to generate some sort of HTML files. It is
-    quite inferior solution compared to docbook, gtkdoc, doxygen but it
-    should work for now.
-    We've a global introduction site (index.html) and then one site for
-    the list of keys (alphabetical sorted) and one for the list of groups,
-    one site for each key with links to the relations and groups.
-
-        index.html
-        all_keys.html
-        all_groups.html
-        groupNAME.html
-        keyNAME.html
-    """
-
-    def replace(self, text, *pairs):
-        """
-        From pydoc... almost identical at least
-        """
-        while pairs:
-            (a, b) = pairs[0]
-            text = join(split(text, a), b)
-            pairs = pairs[1:]
-        return text
-    def escape(self, text):
-        """
-        Escape string to be conform HTML
-        """
-        return self.replace(text, 
-                            ('&', '&amp;'), 
-                            ('<', '&lt;' ),
-                            ('>', '&gt;' ) )
-    def createNavigator(self):
-        """
-        Create the navgiator
-        """
-        return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
-<tr valign="middle">
-<td><a accesskey="g" href="index.html">Home</a></td>
-<td><a accesskey="n" href="all_groups.html">Groups</a></td>
-<td><a accesskey="u" href="all_keys.html">Keys</a></td>
-</tr></table>
-"""
-
-    def relatedKeys(self, item):
-        """
-        Create HTML to link to foreign keys
-        """
-
-        if len(item.related()) == 0:
-            return ""
-
-        txt = "<p><b>See also:</b><br>"
-        txts = []
-        for it in item.related():
-            txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() )
-
-        return txt + ",".join(txts)
-
-    def groups(self, item):
-        """
-        Create HTML to link to related groups
-        """
-
-        if len(item.groups()) == 0:
-            return ""
-
-
-        txt = "<p><b>See also:</b><br>"
-        txts = []
-        for group in item.groups():
-            txts.append( """<a href="group%s.html">%s</a> """ % (group, group) )
-
-        return txt + ",".join(txts)
-
-
-    def createKeySite(self, item):
-        """
-        Create a site for a key. It contains the header/navigator, a heading,
-        the description, links to related keys and to the groups.
-        """
-
-        return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Key %s</title></head>
-<link rel="stylesheet" href="style.css" type="text/css">
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-%s
-<h2><span class="refentrytitle">%s</span></h2>
-
-<div class="refsynopsisdiv">
-<h2>Synopsis</h2>
-<p>
-%s
-</p>
-</div>
-
-<div class="refsynopsisdiv">
-<h2>Related Keys</h2>
-<p>
-%s
-</p>
-</div>
-
-<div class="refsynopsisdiv">
-<h2>Groups</h2>
-<p>
-%s
-</p>
-</div>
-
-
-</body>
-"""     % (item.name(), self.createNavigator(), item.name(), 
-           self.escape(item.description()), self.relatedKeys(item), self.groups(item))
-
-    def createGroupsSite(self, doc):
-        """
-        Create the Group Overview site
-        """
-
-        groups = ""
-        sorted_groups = sorted(doc.groups())
-        for group in sorted_groups:
-            groups += """<a href="group%s.html">%s</a><br>""" % (group, group)
-
-        return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Group overview</title></head>
-<link rel="stylesheet" href="style.css" type="text/css">
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-%s
-<h2>Available Groups</h2>
-%s
-</body>
-""" % (self.createNavigator(), groups)
-
-    def createIndex(self):
-        """
-        Create the index file
-        """
-
-        return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Bitbake Documentation</title></head>
-<link rel="stylesheet" href="style.css" type="text/css">
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-%s
-<h2>Documentation Entrance</h2>
-<a href="all_groups.html">All available groups</a><br>
-<a href="all_keys.html">All available keys</a><br>
-</body>
-""" % self.createNavigator()
-
-    def createKeysSite(self, doc):
-        """
-        Create Overview of all avilable keys
-        """
-        keys = ""
-        sorted_keys = sorted(doc.doc_keys())
-        for key in sorted_keys:
-            keys += """<a href="key%s.html">%s</a><br>""" % (key, key)
-
-        return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Key overview</title></head>
-<link rel="stylesheet" href="style.css" type="text/css">
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-%s
-<h2>Available Keys</h2>
-%s
-</body>
-""" % (self.createNavigator(), keys)
-
-    def createGroupSite(self, gr, items, _description = None):
-        """
-        Create a site for a group:
-        Group the name of the group, items contain the name of the keys
-        inside this group
-        """
-        groups = ""
-        description = ""
-
-        # create a section with the group descriptions
-        if _description:
-            description  += "<h2 Description of Grozp %s</h2>" % gr
-            description  += _description
-
-        items.sort(lambda x, y:cmp(x.name(), y.name()))
-        for group in items:
-            groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
-
-        return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
-<html><head><title>Group %s</title></head>
-<link rel="stylesheet" href="style.css" type="text/css">
-<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
-%s
-%s
-<div class="refsynopsisdiv">
-<h2>Keys in Group %s</h2>
-<pre class="synopsis">
-%s
-</pre>
-</div>
-</body>
-""" % (gr, self.createNavigator(), description, gr, groups)
-
-
-
-    def createCSS(self):
-        """
-        Create the CSS file
-        """
-        return """.synopsis, .classsynopsis
-{
-  background: #eeeeee;
-  border: solid 1px #aaaaaa;
-  padding: 0.5em;
-}
-.programlisting
-{
-  background: #eeeeff;
-  border: solid 1px #aaaaff;
-  padding: 0.5em;
-}
-.variablelist
-{
-  padding: 4px;
-  margin-left: 3em;
-}
-.variablelist td:first-child
-{
-  vertical-align: top;
-}
-table.navigation
-{
-  background: #ffeeee;
-  border: solid 1px #ffaaaa;
-  margin-top: 0.5em;
-  margin-bottom: 0.5em;
-}
-.navigation a
-{
-  color: #770000;
-}
-.navigation a:visited
-{
-  color: #550000;
-}
-.navigation .title
-{
-  font-size: 200%;
-}
-div.refnamediv
-{
-  margin-top: 2em;
-}
-div.gallery-float
-{
-  float: left;
-  padding: 10px;
-}
-div.gallery-float img
-{
-  border-style: none;
-}
-div.gallery-spacer
-{
-  clear: both;
-}
-a
-{
-  text-decoration: none;
-}
-a:hover
-{
-  text-decoration: underline;
-  color: #FF0000;
-}
-"""
-
-
-
-class DocumentationItem:
-    """
-    A class to hold information about a configuration
-    item. It contains the key name, description, a list of related names,
-    and the group this item is contained in.
-    """
-
-    def __init__(self):
-        self._groups  = []
-        self._related = []
-        self._name    = ""
-        self._desc    = ""
-
-    def groups(self):
-        return self._groups
-
-    def name(self):
-        return self._name
-
-    def description(self):
-        return self._desc
-
-    def related(self):
-        return self._related
-
-    def setName(self, name):
-        self._name = name
-
-    def setDescription(self, desc):
-        self._desc = desc
-
-    def addGroup(self, group):
-        self._groups.append(group)
-
-    def addRelation(self, relation):
-        self._related.append(relation)
-
-    def sort(self):
-        self._related.sort()
-        self._groups.sort()
-
-
-class Documentation:
-    """
-    Holds the documentation... with mappings from key to items...
-    """
-
-    def __init__(self):
-        self.__keys   = {}
-        self.__groups = {}
-
-    def insert_doc_item(self, item):
-        """
-        Insert the Doc Item into the internal list
-        of representation
-        """
-        item.sort()
-        self.__keys[item.name()] = item
-
-        for group in item.groups():
-            if not group in self.__groups:
-                self.__groups[group] = []
-            self.__groups[group].append(item)
-            self.__groups[group].sort()
-
-
-    def doc_item(self, key):
-        """
-        Return the DocumentationInstance describing the key
-        """
-        try:
-            return self.__keys[key]
-        except KeyError:
-            return None
-
-    def doc_keys(self):
-        """
-        Return the documented KEYS (names)
-        """
-        return self.__keys.keys()
-
-    def groups(self):
-        """
-        Return the names of available groups
-        """
-        return self.__groups.keys()
-
-    def group_content(self, group_name):
-        """
-        Return a list of keys/names that are in a specefic
-        group or the empty list
-        """
-        try:
-            return self.__groups[group_name]
-        except KeyError:
-            return []
-
-
-def parse_cmdline(args):
-    """
-    Parse the CMD line and return the result as a n-tuple
-    """
-
-    parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__, __version__))
-    usage  = """%prog [options]
-
-Create a set of html pages (documentation) for a bitbake.conf....
-"""
-
-    # Add the needed options
-    parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
-                       action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
-
-    parser.add_option( "-o", "--output", help = "Output directory for html files",
-                       action = "store", dest = "output", default = "html/" )
-
-    parser.add_option( "-D",  "--debug", help = "Increase the debug level",
-                       action = "count", dest = "debug", default = 0 )
-
-    parser.add_option( "-v", "--verbose", help = "output more chit-char to the terminal",
-                       action = "store_true", dest = "verbose", default = False )
-
-    options, args = parser.parse_args( sys.argv )
- 
-    bb.msg.init_msgconfig(options.verbose, options.debug)
-
-    return options.config, options.output
-
-def main():
-    """
-    The main Method
-    """
-
-    (config_file, output_dir) = parse_cmdline( sys.argv )
-
-    # right to let us load the file now
-    try:
-        documentation = bb.parse.handle( config_file, bb.data.init() )
-    except IOError:
-        bb.fatal( "Unable to open %s" % config_file )
-    except bb.parse.ParseError:
-        bb.fatal( "Unable to parse %s" % config_file )
-
-    if isinstance(documentation, dict):
-        documentation = documentation[""]
-
-    # Assuming we've the file loaded now, we will initialize the 'tree'
-    doc = Documentation()
-
-    # defined states
-    state_begin = 0
-    state_see   = 1
-    state_group = 2
-
-    for key in bb.data.keys(documentation):
-        data   = documentation.getVarFlag(key, "doc", False)
-        if not data:
-            continue
-
-        # The Documentation now starts
-        doc_ins = DocumentationItem()
-        doc_ins.setName(key)
-
-
-        tokens = data.split(' ')
-        state = state_begin
-        string= ""
-        for token in tokens:
-            token = token.strip(',')
-
-            if not state == state_see and token == "@see":
-                state = state_see
-                continue
-            elif not state == state_group and token  == "@group":
-                state = state_group
-                continue
-
-            if state == state_begin:
-                string += " %s" % token
-            elif state == state_see:
-                doc_ins.addRelation(token)
-            elif state == state_group:
-                doc_ins.addGroup(token)
-
-        # set the description
-        doc_ins.setDescription(string)
-        doc.insert_doc_item(doc_ins)
-
-    # let us create the HTML now
-    bb.utils.mkdirhier(output_dir)
-    os.chdir(output_dir)
-
-    # Let us create the sites now. We do it in the following order
-    # Start with the index.html. It will point to sites explaining all
-    # keys and groups
-    html_slave = HTMLFormatter()
-
-    f = file('style.css', 'w')
-    print >> f, html_slave.createCSS()
-
-    f = file('index.html', 'w')
-    print >> f, html_slave.createIndex()
-
-    f = file('all_groups.html', 'w')
-    print >> f, html_slave.createGroupsSite(doc)
-
-    f = file('all_keys.html', 'w')
-    print >> f, html_slave.createKeysSite(doc)
-
-    # now for each group create the site
-    for group in doc.groups():
-        f = file('group%s.html' % group, 'w')
-        print >> f, html_slave.createGroupSite(group, doc.group_content(group))
-
-    # now for the keys
-    for key in doc.doc_keys():
-        f = file('key%s.html' % doc.doc_item(key).name(), 'w')
-        print >> f, html_slave.createKeySite(doc.doc_item(key))
-
-
-if __name__ == "__main__":
-    main()
diff --git a/bitbake/contrib/bbparse-torture.py b/bitbake/contrib/bbparse-torture.py
new file mode 100755
index 00000000..c25d547b
--- /dev/null
+++ b/bitbake/contrib/bbparse-torture.py
@@ -0,0 +1,89 @@
+#! /usr/bin/env python3
+#
+# Copyright (C) 2020 Joshua Watt <JPEWhacker@gmail.com>
+#
+# SPDX-License-Identifier: MIT
+
+import argparse
+import os
+import random
+import shutil
+import signal
+import subprocess
+import sys
+import time
+
+
+def try_unlink(path):
+    try:
+        os.unlink(path)
+    except:
+        pass
+
+
+def main():
+    def cleanup():
+        shutil.rmtree("tmp/cache", ignore_errors=True)
+        try_unlink("bitbake-cookerdaemon.log")
+        try_unlink("bitbake.sock")
+        try_unlink("bitbake.lock")
+
+    parser = argparse.ArgumentParser(
+        description="Bitbake parser torture test",
+        epilog="""
+        A torture test for bitbake's parser. Repeatedly interrupts parsing until
+        bitbake decides to deadlock.
+        """,
+    )
+
+    args = parser.parse_args()
+
+    if not "BUILDDIR" in os.environ:
+        print(
+            "'BUILDDIR' not found in the environment. Did you initialize the build environment?"
+        )
+        return 1
+
+    os.chdir(os.environ["BUILDDIR"])
+
+    run_num = 0
+    while True:
+        if run_num % 100 == 0:
+            print("Calibrating wait time...")
+            cleanup()
+
+            start_time = time.monotonic()
+            r = subprocess.run(["bitbake", "-p"])
+            max_wait_time = time.monotonic() - start_time
+
+            if r.returncode != 0:
+                print("Calibration run exited with %d" % r.returncode)
+                return 1
+
+            print("Maximum wait time is %f seconds" % max_wait_time)
+
+        run_num += 1
+        wait_time = random.random() * max_wait_time
+
+        print("Run #%d" % run_num)
+        print("Will sleep for %f seconds" % wait_time)
+
+        cleanup()
+        with subprocess.Popen(["bitbake", "-p"]) as proc:
+            time.sleep(wait_time)
+            proc.send_signal(signal.SIGINT)
+            try:
+                proc.wait(45)
+            except subprocess.TimeoutExpired:
+                print("Run #%d: Waited too long. Possible deadlock!" % run_num)
+                proc.wait()
+                return 1
+
+            if proc.returncode == 0:
+                print("Exited successfully. Timeout too long?")
+            else:
+                print("Exited with %d" % proc.returncode)
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/bitbake/contrib/hashserv/Dockerfile b/bitbake/contrib/hashserv/Dockerfile
new file mode 100644
index 00000000..d6fc728f
--- /dev/null
+++ b/bitbake/contrib/hashserv/Dockerfile
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: MIT
+#
+# Copyright (c) 2021 Joshua Watt <JPEWhacker@gmail.com>
+# 
+# Dockerfile to build a bitbake hash equivalence server container
+#
+# From the root of the bitbake repository, run:
+#
+#   docker build -f contrib/hashserv/Dockerfile .
+#
+
+FROM alpine:3.13.1
+
+RUN apk add --no-cache python3
+
+COPY bin/bitbake-hashserv /opt/bbhashserv/bin/
+COPY lib/hashserv /opt/bbhashserv/lib/hashserv/
+
+ENTRYPOINT ["/opt/bbhashserv/bin/bitbake-hashserv"]
diff --git a/bitbake/contrib/vim/LICENSE.txt b/bitbake/contrib/vim/LICENSE.txt
new file mode 100644
index 00000000..c7d91502
--- /dev/null
+++ b/bitbake/contrib/vim/LICENSE.txt
@@ -0,0 +1,18 @@
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/bitbake/contrib/vim/ftdetect/bitbake.vim b/bitbake/contrib/vim/ftdetect/bitbake.vim
index 200f8ae4..09fc4dc7 100644
--- a/bitbake/contrib/vim/ftdetect/bitbake.vim
+++ b/bitbake/contrib/vim/ftdetect/bitbake.vim
@@ -6,12 +6,12 @@
 "
 " This sets up the syntax highlighting for BitBake files, like .bb, .bbclass and .inc
 
-if &compatible || version < 600
+if &compatible || version < 600 || exists("b:loaded_bitbake_plugin")
     finish
 endif
 
 " .bb, .bbappend and .bbclass
-au BufNewFile,BufRead *.{bb,bbappend,bbclass}	set filetype=bitbake
+au BufNewFile,BufRead *.{bb,bbappend,bbclass}  set filetype=bitbake
 
 " .inc
 au BufNewFile,BufRead *.inc		set filetype=bitbake
diff --git a/bitbake/contrib/vim/ftplugin/bitbake.vim b/bitbake/contrib/vim/ftplugin/bitbake.vim
index db0d7531..9e8d3e13 100644
--- a/bitbake/contrib/vim/ftplugin/bitbake.vim
+++ b/bitbake/contrib/vim/ftplugin/bitbake.vim
@@ -1,2 +1,13 @@
-set sts=4 sw=4 et
-set cms=#%s
+" Only do this when not done yet for this buffer
+if exists("b:did_ftplugin")
+  finish
+endif
+
+" Don't load another plugin for this buffer
+let b:did_ftplugin = 1
+
+let b:undo_ftplugin = "setl cms< sts< sw< et< sua<"
+
+setlocal commentstring=#\ %s
+setlocal softtabstop=4 shiftwidth=4 expandtab
+setlocal suffixesadd+=.bb,.bbclass
diff --git a/bitbake/contrib/vim/plugin/newbb.vim b/bitbake/contrib/vim/plugin/newbb.vim
old mode 100755
new mode 100644
index 874e3380..3a420273
--- a/bitbake/contrib/vim/plugin/newbb.vim
+++ b/bitbake/contrib/vim/plugin/newbb.vim
@@ -10,7 +10,7 @@
 "
 " Will try to use git to find the user name and email
 
-if &compatible || v:version < 600
+if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
     finish
 endif
 
@@ -25,7 +25,7 @@ endfun
 fun! <SID>GetUserEmail()
     let l:user_email = system("git config --get user.email")
     if v:shell_error
-        return "unknow@user.org"
+        return "unknown@user.org"
     else
         return substitute(l:user_email, "\n", "", "")
 endfun
@@ -41,6 +41,10 @@ fun! BBHeader()
 endfun
 
 fun! NewBBTemplate()
+    if line2byte(line('$') + 1) != -1
+        return
+    endif
+
     let l:paste = &paste
     set nopaste
     
@@ -48,7 +52,7 @@ fun! NewBBTemplate()
     call BBHeader()
 
     " New the bb template
-    put ='DESCRIPTION = \"\"'
+    put ='SUMMARY = \"\"'
     put ='HOMEPAGE = \"\"'
     put ='LICENSE = \"\"' 
     put ='SECTION = \"\"'
@@ -58,7 +62,7 @@ fun! NewBBTemplate()
 
     " Go to the first place to edit
     0
-    /^DESCRIPTION =/
+    /^SUMMARY =/
     exec "normal 2f\""
 
     if paste == 1
@@ -76,7 +80,7 @@ if v:progname =~ "vimdiff"
 endif
 
 augroup NewBB
-    au BufNewFile *.bb
+    au BufNewFile,BufReadPost *.bb
                 \ if g:bb_create_on_empty |
                 \    call NewBBTemplate() |
                 \ endif
diff --git a/bitbake/contrib/vim/plugin/newbbappend.vim b/bitbake/contrib/vim/plugin/newbbappend.vim
new file mode 100644
index 00000000..e04174cf
--- /dev/null
+++ b/bitbake/contrib/vim/plugin/newbbappend.vim
@@ -0,0 +1,46 @@
+" Vim plugin file
+" Purpose:	Create a template for new bbappend file
+" Author:	Joshua Watt <JPEWhacker@gmail.com>
+" Copyright:	Copyright (C) 2017 Joshua Watt <JPEWhacker@gmail.com>
+"
+" This file is licensed under the MIT license, see COPYING.MIT in
+" this source distribution for the terms.
+"
+
+if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
+    finish
+endif
+
+fun! NewBBAppendTemplate()
+    if line2byte(line('$') + 1) != -1
+        return
+    endif
+
+    let l:paste = &paste
+    set nopaste
+
+    " New bbappend template
+    0 put ='FILESEXTRAPATHS_prepend := \"${THISDIR}/${PN}:\"'
+    2
+
+    if paste == 1
+        set paste
+    endif
+endfun
+
+if !exists("g:bb_create_on_empty")
+    let g:bb_create_on_empty = 1
+endif
+
+" disable in case of vimdiff
+if v:progname =~ "vimdiff"
+    let g:bb_create_on_empty = 0
+endif
+
+augroup NewBBAppend
+    au BufNewFile,BufReadPost *.bbappend
+                \ if g:bb_create_on_empty |
+                \    call NewBBAppendTemplate() |
+                \ endif
+augroup END
+
diff --git a/bitbake/contrib/vim/syntax/bitbake.vim b/bitbake/contrib/vim/syntax/bitbake.vim
index fb55f910..f964621a 100644
--- a/bitbake/contrib/vim/syntax/bitbake.vim
+++ b/bitbake/contrib/vim/syntax/bitbake.vim
@@ -12,7 +12,7 @@
 "
 " It's an entirely new type, just has specific syntax in shell and python code
 
-if &compatible || v:version < 600
+if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
     finish
 endif
 if exists("b:current_syntax")
@@ -58,8 +58,8 @@ syn match bbVarValue            ".*$" contained contains=bbString,bbVarDeref,bbV
 syn region bbVarPyValue         start=+${@+ skip=+\\$+ end=+}+ contained contains=@python
 
 " Vars metadata flags
-syn match bbVarFlagDef          "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
-syn region bbVarFlagFlag        matchgroup=bbArrayBrackets start="\[" end="\]\s*\(=\|+=\|=+\|?=\)\@=" contained contains=bbIdentifier nextgroup=bbVarEq
+syn match bbVarFlagDef          "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.+]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
+syn region bbVarFlagFlag        matchgroup=bbArrayBrackets start="\[" end="\]\s*\(:=\|=\|.=\|=.|+=\|=+\|?=\)\@=" contained contains=bbIdentifier nextgroup=bbVarEq
 
 " Includes and requires
 syn keyword bbInclude           inherit include require contained 
@@ -67,15 +67,15 @@ syn match bbIncludeRest         ".*$" contained contains=bbString,bbVarDeref
 syn match bbIncludeLine         "^\(inherit\|include\|require\)\s\+" contains=bbInclude nextgroup=bbIncludeRest
 
 " Add taks and similar
-syn keyword bbStatement         addtask addhandler after before EXPORT_FUNCTIONS contained
+syn keyword bbStatement         addtask deltask addhandler after before EXPORT_FUNCTIONS contained
 syn match bbStatementRest       ".*$" skipwhite contained contains=bbStatement
-syn match bbStatementLine       "^\(addtask\|addhandler\|after\|before\|EXPORT_FUNCTIONS\)\s\+" contains=bbStatement nextgroup=bbStatementRest
+syn match bbStatementLine       "^\(addtask\|deltask\|addhandler\|after\|before\|EXPORT_FUNCTIONS\)\s\+" contains=bbStatement nextgroup=bbStatementRest
 
 " OE Important Functions
 syn keyword bbOEFunctions       do_fetch do_unpack do_patch do_configure do_compile do_stage do_install do_package contained
 
 " Generic Functions
-syn match bbFunction            "\h[0-9A-Za-z_-]*" display contained contains=bbOEFunctions
+syn match bbFunction            "\h[0-9A-Za-z_\-\.]*" display contained contains=bbOEFunctions
 
 " BitBake shell metadata
 syn include @shell syntax/sh.vim
@@ -83,7 +83,7 @@ if exists("b:current_syntax")
   unlet b:current_syntax
 endif
 syn keyword bbShFakeRootFlag    fakeroot contained
-syn match bbShFuncDef           "^\(fakeroot\s*\)\?\([0-9A-Za-z_${}-]\+\)\(python\)\@<!\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbShFuncRegion skipwhite
+syn match bbShFuncDef           "^\(fakeroot\s*\)\?\([\.0-9A-Za-z_${}\-\.]\+\)\(python\)\@<!\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbShFuncRegion skipwhite
 syn region bbShFuncRegion       matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@shell
 
 " Python value inside shell functions
@@ -91,7 +91,7 @@ syn region shDeref         start=+${@+ skip=+\\$+ excludenl end=+}+ contained co
 
 " BitBake python metadata
 syn keyword bbPyFlag            python contained
-syn match bbPyFuncDef           "^\(python\s\+\)\([0-9A-Za-z_${}-]\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbPyFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbPyFuncRegion skipwhite
+syn match bbPyFuncDef           "^\(fakeroot\s*\)\?\(python\)\(\s\+[0-9A-Za-z_${}\-\.]\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbPyFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbPyFuncRegion skipwhite
 syn region bbPyFuncRegion       matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@python
 
 " BitBake 'def'd python functions
diff --git a/bitbake/doc/.gitignore b/bitbake/doc/.gitignore
new file mode 100644
index 00000000..69fa449d
--- /dev/null
+++ b/bitbake/doc/.gitignore
@@ -0,0 +1 @@
+_build/
diff --git a/bitbake/doc/Makefile b/bitbake/doc/Makefile
index 3c28f4b2..d40f390e 100644
--- a/bitbake/doc/Makefile
+++ b/bitbake/doc/Makefile
@@ -1,91 +1,35 @@
-# This is a single Makefile to handle all generated BitBake documents.
-# The Makefile needs to live in the documentation directory and all figures used
-# in any manuals must be .PNG files and live in the individual book's figures
-# directory.
-#
-# The Makefile has these targets:
-#
-#    pdf:      generates a PDF version of a manual.
-#    html:     generates an HTML version of a manual.
-#    tarball:  creates a tarball for the doc files.
-#    validate: validates
-#    clean:    removes files
-#
-# The Makefile generates an HTML version of every document.  The
-# variable DOC indicates the folder name for a given manual.
-#
-# To build a manual, you must invoke 'make' with the DOC argument.
-#
-# Examples:
-#
-#     make DOC=bitbake-user-manual
-#     make pdf DOC=bitbake-user-manual
-#
-# The first example generates the HTML version of the User Manual.
-# The second example generates the PDF version of the User Manual.
+# Minimal makefile for Sphinx documentation
 #
 
-ifeq ($(DOC),bitbake-user-manual)
-XSLTOPTS = --stringparam html.stylesheet bitbake-user-manual-style.css \
-           --stringparam  chapter.autolabel 1 \
-           --stringparam  section.autolabel 1 \
-           --stringparam  section.label.includes.component.label 1 \
-           --xinclude
-ALLPREQ = html tarball
-TARFILES = bitbake-user-manual-style.css bitbake-user-manual.html figures/bitbake-title.png
-MANUALS = $(DOC)/$(DOC).html
-FIGURES = figures
-STYLESHEET = $(DOC)/*.css
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS    ?= -j auto
+SPHINXBUILD   ?= sphinx-build
+SOURCEDIR     = .
+BUILDDIR      = _build
+DESTDIR       = final
 
+ifeq ($(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi),0)
+$(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed")
 endif
 
-##
-# These URI should be rewritten by your distribution's xml catalog to
-# match your localy installed XSL stylesheets.
-XSL_BASE_URI  = http://docbook.sourceforge.net/release/xsl/current
-XSL_XHTML_URI = $(XSL_BASE_URI)/xhtml/docbook.xsl
+# Put it first so that "make" without argument is like "make help".
+help:
+	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
 
-all: $(ALLPREQ)
+.PHONY: help Makefile clean publish
 
-pdf:
-ifeq ($(DOC),bitbake-user-manual)
-	@echo " "
-	@echo "********** Building."$(DOC)
-	@echo " "
-	cd $(DOC); ../tools/docbook-to-pdf $(DOC).xml ../template; cd ..
-endif
-
-html:
-ifeq ($(DOC),bitbake-user-manual)
-#       See http://www.sagehill.net/docbookxsl/HtmlOutput.html
-	@echo " "
-	@echo "******** Building "$(DOC)
-	@echo " "
-	cd $(DOC); xsltproc $(XSLTOPTS) -o $(DOC).html $(DOC)-customization.xsl $(DOC).xml; cd ..
-endif
-
-tarball: html
-	@echo " "
-	@echo "******** Creating Tarball of document files"
-	@echo " "
-	cd $(DOC); tar -cvzf $(DOC).tgz $(TARFILES); cd ..
-
-validate:
-	cd $(DOC); xmllint --postvalid --xinclude --noout $(DOC).xml; cd ..
-
-publish:
-	@if test -f $(DOC)/$(DOC).html; \
-	  then \
-            echo " "; \
-            echo "******** Publishing "$(DOC)".html"; \
-            echo " "; \
-            scp -r $(MANUALS) $(STYLESHEET) docs.yp:/var/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
-            cd $(DOC); scp -r $(FIGURES) docs.yp:/var/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
-	else \
-          echo " "; \
-          echo $(DOC)".html missing.  Generate the file first then try again."; \
-          echo " "; \
-	fi
+publish: Makefile html singlehtml
+	rm -rf $(BUILDDIR)/$(DESTDIR)/
+	mkdir -p $(BUILDDIR)/$(DESTDIR)/
+	cp -r $(BUILDDIR)/html/* $(BUILDDIR)/$(DESTDIR)/
+	cp $(BUILDDIR)/singlehtml/index.html $(BUILDDIR)/$(DESTDIR)/singleindex.html
+	sed -i -e 's@index.html#@singleindex.html#@g' $(BUILDDIR)/$(DESTDIR)/singleindex.html
 
 clean:
-	rm -rf $(MANUALS); rm $(DOC)/$(DOC).tgz;
+	@rm -rf $(BUILDDIR)
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/bitbake/doc/README b/bitbake/doc/README
index 303cf8ee..cbb5215d 100644
--- a/bitbake/doc/README
+++ b/bitbake/doc/README
@@ -15,25 +15,41 @@ Each folder is self-contained regarding content and figures.
 If you want to find HTML versions of the BitBake manuals on the web, 
 go to http://www.openembedded.org/wiki/Documentation. 
 
-Makefile
-========
+Sphinx
+======
 
-The Makefile processes manual directories to create HTML, PDF,
-tarballs, etc.  Details on how the Makefile work are documented
-inside the Makefile.  See that file for more information.
+The BitBake documentation was migrated from the original DocBook
+format to Sphinx based documentation for the Yocto Project 3.2
+release.
 
-To build a manual, you run the make command and pass it the name
-of the folder containing the manual's contents. 
-For example, the following command run from the documentation directory 
-creates an HTML and a PDF version of the BitBake User Manual.
-The DOC variable specifies the manual you are making:
+Additional information related to the Sphinx migration, and guidelines
+for developers willing to contribute to the BitBake documentation can
+be found in the Yocto Project Documentation README file:
 
-     $ make DOC=bitbake-user-manual
+https://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/tree/documentation/README
 
-template
-========
-Contains various templates, fonts, and some old PNG files.
+How to build the Yocto Project documentation
+============================================
 
-tools
-=====
-Contains a tool to convert the DocBook files to PDF format.
+Sphinx is written in Python. While it might work with Python2, for
+obvious reasons, we will only support building the BitBake
+documentation with Python3.
+
+Sphinx might be available in your Linux distro packages repositories,
+however it is not recommend using distro packages, as they might be
+old versions, especially if you are using an LTS version of your
+distro. The recommended method to install Sphinx and all required
+dependencies is to use the Python Package Index (pip).
+
+To install all required packages run:
+
+ $ pip3 install sphinx sphinx_rtd_theme pyyaml
+
+To build the documentation locally, run:
+
+ $ cd documentation
+ $ make html
+
+The resulting HTML index page will be _build/html/index.html, and you
+can browse your own copy of the locally generated documentation with
+your browser.
diff --git a/bitbake/doc/_templates/breadcrumbs.html b/bitbake/doc/_templates/breadcrumbs.html
new file mode 100644
index 00000000..eb6244b7
--- /dev/null
+++ b/bitbake/doc/_templates/breadcrumbs.html
@@ -0,0 +1,14 @@
+{% extends "!breadcrumbs.html" %}
+
+{% block breadcrumbs %}
+    <li>
+      <span class="doctype_switcher_placeholder">{{ doctype or 'single' }}</span>
+      <span class="version_switcher_placeholder">{{ release }}</span>
+    </li>
+    <li> &raquo;</li>
+    {% for doc in parents %}
+      <li><a href="{{ doc.link|e }}">{{ doc.title }}</a> &raquo;</li>
+    {% endfor %}
+    <li>{{ title }}</li>
+{% endblock %}
+
diff --git a/bitbake/doc/_templates/layout.html b/bitbake/doc/_templates/layout.html
new file mode 100644
index 00000000..308d5c7a
--- /dev/null
+++ b/bitbake/doc/_templates/layout.html
@@ -0,0 +1,7 @@
+{% extends "!layout.html" %}
+
+{% block extrabody %}
+<div id="outdated-warning" style="text-align: center; background-color: #FFBABA; color: #6A0E0E;">
+</div>
+{% endblock %}
+
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-customization.xsl b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-customization.xsl
deleted file mode 100644
index 5985ea78..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-customization.xsl
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version='1.0'?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
-
-  <xsl:import href="http://downloads.yoctoproject.org/mirror/docbook-mirror/docbook-xsl-1.76.1/xhtml/docbook.xsl" />
-
-<!--
-
-  <xsl:import href="../template/1.76.1/docbook-xsl-1.76.1/xhtml/docbook.xsl" />
-
-  <xsl:import href="http://docbook.sourceforge.net/release/xsl/1.76.1/xhtml/docbook.xsl" />
-
--->
-
-  <xsl:include href="../template/permalinks.xsl"/>
-  <xsl:include href="../template/section.title.xsl"/>
-  <xsl:include href="../template/component.title.xsl"/>
-  <xsl:include href="../template/division.title.xsl"/>
-  <xsl:include href="../template/formal.object.heading.xsl"/>
-  <xsl:include href="../template/gloss-permalinks.xsl"/>
-
-  <xsl:param name="html.stylesheet" select="'user-manual-style.css'" />
-  <xsl:param name="chapter.autolabel" select="1" />
-  <xsl:param name="section.autolabel" select="1" />
-  <xsl:param name="section.label.includes.component.label" select="1" />
-  <xsl:param name="appendix.autolabel">A</xsl:param>
-
-<!--  <xsl:param name="generate.toc" select="'article nop'"></xsl:param>  -->
-
-</xsl:stylesheet>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.rst
new file mode 100644
index 00000000..56abf773
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.rst
@@ -0,0 +1,734 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+=========
+Execution
+=========
+
+|
+
+The primary purpose for running BitBake is to produce some kind of
+output such as a single installable package, a kernel, a software
+development kit, or even a full, board-specific bootable Linux image,
+complete with bootloader, kernel, and root filesystem. Of course, you
+can execute the ``bitbake`` command with options that cause it to
+execute single tasks, compile single recipe files, capture or clear
+data, or simply return information about the execution environment.
+
+This chapter describes BitBake's execution process from start to finish
+when you use it to create an image. The execution process is launched
+using the following command form: ::
+
+  $ bitbake target
+
+For information on
+the BitBake command and its options, see ":ref:`The BitBake Command
+<bitbake-user-manual-command>`" section.
+
+.. note::
+
+   Prior to executing BitBake, you should take advantage of available
+   parallel thread execution on your build host by setting the
+   :term:`BB_NUMBER_THREADS` variable in
+   your project's ``local.conf`` configuration file.
+
+   A common method to determine this value for your build host is to run
+   the following: ::
+
+     $ grep processor /proc/cpuinfo
+
+   This command returns
+   the number of processors, which takes into account hyper-threading.
+   Thus, a quad-core build host with hyper-threading most likely shows
+   eight processors, which is the value you would then assign to
+   ``BB_NUMBER_THREADS``.
+
+   A possibly simpler solution is that some Linux distributions (e.g.
+   Debian and Ubuntu) provide the ``ncpus`` command.
+
+Parsing the Base Configuration Metadata
+=======================================
+
+The first thing BitBake does is parse base configuration metadata. Base
+configuration metadata consists of your project's ``bblayers.conf`` file
+to determine what layers BitBake needs to recognize, all necessary
+``layer.conf`` files (one from each layer), and ``bitbake.conf``. The
+data itself is of various types:
+
+-  **Recipes:** Details about particular pieces of software.
+
+-  **Class Data:** An abstraction of common build information (e.g. how to
+   build a Linux kernel).
+
+-  **Configuration Data:** Machine-specific settings, policy decisions,
+   and so forth. Configuration data acts as the glue to bind everything
+   together.
+
+The ``layer.conf`` files are used to construct key variables such as
+:term:`BBPATH` and :term:`BBFILES`.
+``BBPATH`` is used to search for configuration and class files under the
+``conf`` and ``classes`` directories, respectively. ``BBFILES`` is used
+to locate both recipe and recipe append files (``.bb`` and
+``.bbappend``). If there is no ``bblayers.conf`` file, it is assumed the
+user has set the ``BBPATH`` and ``BBFILES`` directly in the environment.
+
+Next, the ``bitbake.conf`` file is located using the ``BBPATH`` variable
+that was just constructed. The ``bitbake.conf`` file may also include
+other configuration files using the ``include`` or ``require``
+directives.
+
+Prior to parsing configuration files, BitBake looks at certain
+variables, including:
+
+-  :term:`BB_ENV_WHITELIST`
+-  :term:`BB_ENV_EXTRAWHITE`
+-  :term:`BB_PRESERVE_ENV`
+-  :term:`BB_ORIGENV`
+-  :term:`BITBAKE_UI`
+
+The first four variables in this list relate to how BitBake treats shell
+environment variables during task execution. By default, BitBake cleans
+the environment variables and provides tight control over the shell
+execution environment. However, through the use of these first four
+variables, you can apply your control regarding the environment
+variables allowed to be used by BitBake in the shell during execution of
+tasks. See the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:Passing Information Into the Build Task Environment`"
+section and the information about these variables in the variable
+glossary for more information on how they work and on how to use them.
+
+The base configuration metadata is global and therefore affects all
+recipes and tasks that are executed.
+
+BitBake first searches the current working directory for an optional
+``conf/bblayers.conf`` configuration file. This file is expected to
+contain a :term:`BBLAYERS` variable that is a
+space-delimited list of 'layer' directories. Recall that if BitBake
+cannot find a ``bblayers.conf`` file, then it is assumed the user has
+set the ``BBPATH`` and ``BBFILES`` variables directly in the
+environment.
+
+For each directory (layer) in this list, a ``conf/layer.conf`` file is
+located and parsed with the :term:`LAYERDIR` variable
+being set to the directory where the layer was found. The idea is these
+files automatically set up :term:`BBPATH` and other
+variables correctly for a given build directory.
+
+BitBake then expects to find the ``conf/bitbake.conf`` file somewhere in
+the user-specified ``BBPATH``. That configuration file generally has
+include directives to pull in any other metadata such as files specific
+to the architecture, the machine, the local environment, and so forth.
+
+Only variable definitions and include directives are allowed in BitBake
+``.conf`` files. Some variables directly influence BitBake's behavior.
+These variables might have been set from the environment depending on
+the environment variables previously mentioned or set in the
+configuration files. The ":ref:`bitbake-user-manual/bitbake-user-manual-ref-variables:Variables Glossary`"
+chapter presents a full list of
+variables.
+
+After parsing configuration files, BitBake uses its rudimentary
+inheritance mechanism, which is through class files, to inherit some
+standard classes. BitBake parses a class when the inherit directive
+responsible for getting that class is encountered.
+
+The ``base.bbclass`` file is always included. Other classes that are
+specified in the configuration using the
+:term:`INHERIT` variable are also included. BitBake
+searches for class files in a ``classes`` subdirectory under the paths
+in ``BBPATH`` in the same way as configuration files.
+
+A good way to get an idea of the configuration files and the class files
+used in your execution environment is to run the following BitBake
+command: ::
+
+  $ bitbake -e > mybb.log
+
+Examining the top of the ``mybb.log``
+shows you the many configuration files and class files used in your
+execution environment.
+
+.. note::
+
+   You need to be aware of how BitBake parses curly braces. If a recipe
+   uses a closing curly brace within the function and the character has
+   no leading spaces, BitBake produces a parsing error. If you use a
+   pair of curly braces in a shell function, the closing curly brace
+   must not be located at the start of the line without leading spaces.
+
+   Here is an example that causes BitBake to produce a parsing error: ::
+
+      fakeroot create_shar() {
+         cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
+      usage()
+      {
+         echo "test"
+         ######  The following "}" at the start of the line causes a parsing error ######
+      }
+      EOF
+      }
+
+      Writing the recipe this way avoids the error:
+      fakeroot create_shar() {
+         cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
+      usage()
+      {
+         echo "test"
+         ###### The following "}" with a leading space at the start of the line avoids the error ######
+       }
+      EOF
+      }
+
+Locating and Parsing Recipes
+============================
+
+During the configuration phase, BitBake will have set
+:term:`BBFILES`. BitBake now uses it to construct a
+list of recipes to parse, along with any append files (``.bbappend``) to
+apply. ``BBFILES`` is a space-separated list of available files and
+supports wildcards. An example would be: ::
+
+  BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"
+
+BitBake parses each
+recipe and append file located with ``BBFILES`` and stores the values of
+various variables into the datastore.
+
+.. note::
+
+   Append files are applied in the order they are encountered in BBFILES.
+
+For each file, a fresh copy of the base configuration is made, then the
+recipe is parsed line by line. Any inherit statements cause BitBake to
+find and then parse class files (``.bbclass``) using
+:term:`BBPATH` as the search path. Finally, BitBake
+parses in order any append files found in ``BBFILES``.
+
+One common convention is to use the recipe filename to define pieces of
+metadata. For example, in ``bitbake.conf`` the recipe name and version
+are used to set the variables :term:`PN` and
+:term:`PV`: ::
+
+   PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
+   PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
+
+In this example, a recipe called "something_1.2.3.bb" would set
+``PN`` to "something" and ``PV`` to "1.2.3".
+
+By the time parsing is complete for a recipe, BitBake has a list of
+tasks that the recipe defines and a set of data consisting of keys and
+values as well as dependency information about the tasks.
+
+BitBake does not need all of this information. It only needs a small
+subset of the information to make decisions about the recipe.
+Consequently, BitBake caches the values in which it is interested and
+does not store the rest of the information. Experience has shown it is
+faster to re-parse the metadata than to try and write it out to the disk
+and then reload it.
+
+Where possible, subsequent BitBake commands reuse this cache of recipe
+information. The validity of this cache is determined by first computing
+a checksum of the base configuration data (see
+:term:`BB_HASHCONFIG_WHITELIST`) and
+then checking if the checksum matches. If that checksum matches what is
+in the cache and the recipe and class files have not changed, BitBake is
+able to use the cache. BitBake then reloads the cached information about
+the recipe instead of reparsing it from scratch.
+
+Recipe file collections exist to allow the user to have multiple
+repositories of ``.bb`` files that contain the same exact package. For
+example, one could easily use them to make one's own local copy of an
+upstream repository, but with custom modifications that one does not
+want upstream. Here is an example: ::
+
+  BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
+  BBFILE_COLLECTIONS = "upstream local"
+  BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
+  BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
+  BBFILE_PRIORITY_upstream = "5"
+  BBFILE_PRIORITY_local = "10"
+
+.. note::
+
+   The layers mechanism is now the preferred method of collecting code.
+   While the collections code remains, its main use is to set layer
+   priorities and to deal with overlap (conflicts) between layers.
+
+.. _bb-bitbake-providers:
+
+Providers
+=========
+
+Assuming BitBake has been instructed to execute a target and that all
+the recipe files have been parsed, BitBake starts to figure out how to
+build the target. BitBake looks through the ``PROVIDES`` list for each
+of the recipes. A ``PROVIDES`` list is the list of names by which the
+recipe can be known. Each recipe's ``PROVIDES`` list is created
+implicitly through the recipe's :term:`PN` variable and
+explicitly through the recipe's :term:`PROVIDES`
+variable, which is optional.
+
+When a recipe uses ``PROVIDES``, that recipe's functionality can be
+found under an alternative name or names other than the implicit ``PN``
+name. As an example, suppose a recipe named ``keyboard_1.0.bb``
+contained the following: ::
+
+  PROVIDES += "fullkeyboard"
+
+The ``PROVIDES``
+list for this recipe becomes "keyboard", which is implicit, and
+"fullkeyboard", which is explicit. Consequently, the functionality found
+in ``keyboard_1.0.bb`` can be found under two different names.
+
+.. _bb-bitbake-preferences:
+
+Preferences
+===========
+
+The ``PROVIDES`` list is only part of the solution for figuring out a
+target's recipes. Because targets might have multiple providers, BitBake
+needs to prioritize providers by determining provider preferences.
+
+A common example in which a target has multiple providers is
+"virtual/kernel", which is on the ``PROVIDES`` list for each kernel
+recipe. Each machine often selects the best kernel provider by using a
+line similar to the following in the machine configuration file: ::
+
+  PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
+
+The default :term:`PREFERRED_PROVIDER` is the provider
+with the same name as the target. BitBake iterates through each target
+it needs to build and resolves them and their dependencies using this
+process.
+
+Understanding how providers are chosen is made complicated by the fact
+that multiple versions might exist for a given provider. BitBake
+defaults to the highest version of a provider. Version comparisons are
+made using the same method as Debian. You can use the
+:term:`PREFERRED_VERSION` variable to
+specify a particular version. You can influence the order by using the
+:term:`DEFAULT_PREFERENCE` variable.
+
+By default, files have a preference of "0". Setting
+``DEFAULT_PREFERENCE`` to "-1" makes the recipe unlikely to be used
+unless it is explicitly referenced. Setting ``DEFAULT_PREFERENCE`` to
+"1" makes it likely the recipe is used. ``PREFERRED_VERSION`` overrides
+any ``DEFAULT_PREFERENCE`` setting. ``DEFAULT_PREFERENCE`` is often used
+to mark newer and more experimental recipe versions until they have
+undergone sufficient testing to be considered stable.
+
+When there are multiple "versions" of a given recipe, BitBake defaults
+to selecting the most recent version, unless otherwise specified. If the
+recipe in question has a
+:term:`DEFAULT_PREFERENCE` set lower than
+the other recipes (default is 0), then it will not be selected. This
+allows the person or persons maintaining the repository of recipe files
+to specify their preference for the default selected version.
+Additionally, the user can specify their preferred version.
+
+If the first recipe is named ``a_1.1.bb``, then the
+:term:`PN` variable will be set to "a", and the
+:term:`PV` variable will be set to 1.1.
+
+Thus, if a recipe named ``a_1.2.bb`` exists, BitBake will choose 1.2 by
+default. However, if you define the following variable in a ``.conf``
+file that BitBake parses, you can change that preference: ::
+
+  PREFERRED_VERSION_a = "1.1"
+
+.. note::
+
+   It is common for a recipe to provide two versions -- a stable,
+   numbered (and preferred) version, and a version that is automatically
+   checked out from a source code repository that is considered more
+   "bleeding edge" but can be selected only explicitly.
+
+   For example, in the OpenEmbedded codebase, there is a standard,
+   versioned recipe file for BusyBox, ``busybox_1.22.1.bb``, but there
+   is also a Git-based version, ``busybox_git.bb``, which explicitly
+   contains the line ::
+
+     DEFAULT_PREFERENCE = "-1"
+
+   to ensure that the
+   numbered, stable version is always preferred unless the developer
+   selects otherwise.
+
+.. _bb-bitbake-dependencies:
+
+Dependencies
+============
+
+Each target BitBake builds consists of multiple tasks such as ``fetch``,
+``unpack``, ``patch``, ``configure``, and ``compile``. For best
+performance on multi-core systems, BitBake considers each task as an
+independent entity with its own set of dependencies.
+
+Dependencies are defined through several variables. You can find
+information about variables BitBake uses in the
+:doc:`bitbake-user-manual-ref-variables` near the end of this manual. At a
+basic level, it is sufficient to know that BitBake uses the
+:term:`DEPENDS` and
+:term:`RDEPENDS` variables when calculating
+dependencies.
+
+For more information on how BitBake handles dependencies, see the
+:ref:`bitbake-user-manual/bitbake-user-manual-metadata:Dependencies`
+section.
+
+.. _ref-bitbake-tasklist:
+
+The Task List
+=============
+
+Based on the generated list of providers and the dependency information,
+BitBake can now calculate exactly what tasks it needs to run and in what
+order it needs to run them. The
+:ref:`bitbake-user-manual/bitbake-user-manual-execution:executing tasks`
+section has more information on how BitBake chooses which task to
+execute next.
+
+The build now starts with BitBake forking off threads up to the limit
+set in the :term:`BB_NUMBER_THREADS`
+variable. BitBake continues to fork threads as long as there are tasks
+ready to run, those tasks have all their dependencies met, and the
+thread threshold has not been exceeded.
+
+It is worth noting that you can greatly speed up the build time by
+properly setting the ``BB_NUMBER_THREADS`` variable.
+
+As each task completes, a timestamp is written to the directory
+specified by the :term:`STAMP` variable. On subsequent
+runs, BitBake looks in the build directory within ``tmp/stamps`` and
+does not rerun tasks that are already completed unless a timestamp is
+found to be invalid. Currently, invalid timestamps are only considered
+on a per recipe file basis. So, for example, if the configure stamp has
+a timestamp greater than the compile timestamp for a given target, then
+the compile task would rerun. Running the compile task again, however,
+has no effect on other providers that depend on that target.
+
+The exact format of the stamps is partly configurable. In modern
+versions of BitBake, a hash is appended to the stamp so that if the
+configuration changes, the stamp becomes invalid and the task is
+automatically rerun. This hash, or signature used, is governed by the
+signature policy that is configured (see the
+:ref:`bitbake-user-manual/bitbake-user-manual-execution:checksums (signatures)`
+section for information). It is also
+possible to append extra metadata to the stamp using the
+``[stamp-extra-info]`` task flag. For example, OpenEmbedded uses this
+flag to make some tasks machine-specific.
+
+.. note::
+
+   Some tasks are marked as "nostamp" tasks. No timestamp file is
+   created when these tasks are run. Consequently, "nostamp" tasks are
+   always rerun.
+
+For more information on tasks, see the
+:ref:`bitbake-user-manual/bitbake-user-manual-metadata:tasks` section.
+
+Executing Tasks
+===============
+
+Tasks can be either a shell task or a Python task. For shell tasks,
+BitBake writes a shell script to
+``${``\ :term:`T`\ ``}/run.do_taskname.pid`` and then
+executes the script. The generated shell script contains all the
+exported variables, and the shell functions with all variables expanded.
+Output from the shell script goes to the file
+``${T}/log.do_taskname.pid``. Looking at the expanded shell functions in
+the run file and the output in the log files is a useful debugging
+technique.
+
+For Python tasks, BitBake executes the task internally and logs
+information to the controlling terminal. Future versions of BitBake will
+write the functions to files similar to the way shell tasks are handled.
+Logging will be handled in a way similar to shell tasks as well.
+
+The order in which BitBake runs the tasks is controlled by its task
+scheduler. It is possible to configure the scheduler and define custom
+implementations for specific use cases. For more information, see these
+variables that control the behavior:
+
+-  :term:`BB_SCHEDULER`
+
+-  :term:`BB_SCHEDULERS`
+
+It is possible to have functions run before and after a task's main
+function. This is done using the ``[prefuncs]`` and ``[postfuncs]``
+flags of the task that lists the functions to run.
+
+.. _checksums:
+
+Checksums (Signatures)
+======================
+
+A checksum is a unique signature of a task's inputs. The signature of a
+task can be used to determine if a task needs to be run. Because it is a
+change in a task's inputs that triggers running the task, BitBake needs
+to detect all the inputs to a given task. For shell tasks, this turns
+out to be fairly easy because BitBake generates a "run" shell script for
+each task and it is possible to create a checksum that gives you a good
+idea of when the task's data changes.
+
+To complicate the problem, some things should not be included in the
+checksum. First, there is the actual specific build path of a given task
+- the working directory. It does not matter if the working directory
+changes because it should not affect the output for target packages. The
+simplistic approach for excluding the working directory is to set it to
+some fixed value and create the checksum for the "run" script. BitBake
+goes one step better and uses the
+:term:`BB_HASHBASE_WHITELIST` variable
+to define a list of variables that should never be included when
+generating the signatures.
+
+Another problem results from the "run" scripts containing functions that
+might or might not get called. The incremental build solution contains
+code that figures out dependencies between shell functions. This code is
+used to prune the "run" scripts down to the minimum set, thereby
+alleviating this problem and making the "run" scripts much more readable
+as a bonus.
+
+So far we have solutions for shell scripts. What about Python tasks? The
+same approach applies even though these tasks are more difficult. The
+process needs to figure out what variables a Python function accesses
+and what functions it calls. Again, the incremental build solution
+contains code that first figures out the variable and function
+dependencies, and then creates a checksum for the data used as the input
+to the task.
+
+Like the working directory case, situations exist where dependencies
+should be ignored. For these cases, you can instruct the build process
+to ignore a dependency by using a line like the following: ::
+
+  PACKAGE_ARCHS[vardepsexclude] = "MACHINE"
+
+This example ensures that the
+``PACKAGE_ARCHS`` variable does not depend on the value of ``MACHINE``,
+even if it does reference it.
+
+Equally, there are cases where we need to add dependencies BitBake is
+not able to find. You can accomplish this by using a line like the
+following: ::
+
+  PACKAGE_ARCHS[vardeps] = "MACHINE"
+
+This example explicitly
+adds the ``MACHINE`` variable as a dependency for ``PACKAGE_ARCHS``.
+
+Consider a case with in-line Python, for example, where BitBake is not
+able to figure out dependencies. When running in debug mode (i.e. using
+``-DDD``), BitBake produces output when it discovers something for which
+it cannot figure out dependencies.
+
+Thus far, this section has limited discussion to the direct inputs into
+a task. Information based on direct inputs is referred to as the
+"basehash" in the code. However, there is still the question of a task's
+indirect inputs - the things that were already built and present in the
+build directory. The checksum (or signature) for a particular task needs
+to add the hashes of all the tasks on which the particular task depends.
+Choosing which dependencies to add is a policy decision. However, the
+effect is to generate a master checksum that combines the basehash and
+the hashes of the task's dependencies.
+
+At the code level, there are a variety of ways both the basehash and the
+dependent task hashes can be influenced. Within the BitBake
+configuration file, we can give BitBake some extra information to help
+it construct the basehash. The following statement effectively results
+in a list of global variable dependency excludes - variables never
+included in any checksum. This example uses variables from OpenEmbedded
+to help illustrate the concept: ::
+
+   BB_HASHBASE_WHITELIST ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
+       SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL \
+       USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
+       PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
+       CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"
+
+The previous example excludes the work directory, which is part of
+``TMPDIR``.
+
+The rules for deciding which hashes of dependent tasks to include
+through dependency chains are more complex and are generally
+accomplished with a Python function. The code in
+``meta/lib/oe/sstatesig.py`` shows two examples of this and also
+illustrates how you can insert your own policy into the system if so
+desired. This file defines the two basic signature generators
+OpenEmbedded-Core uses: "OEBasic" and "OEBasicHash". By default, there
+is a dummy "noop" signature handler enabled in BitBake. This means that
+behavior is unchanged from previous versions. ``OE-Core`` uses the
+"OEBasicHash" signature handler by default through this setting in the
+``bitbake.conf`` file: ::
+
+  BB_SIGNATURE_HANDLER ?= "OEBasicHash"
+
+The "OEBasicHash" ``BB_SIGNATURE_HANDLER`` is the same as the "OEBasic"
+version but adds the task hash to the stamp files. This results in any
+metadata change that changes the task hash, automatically causing the
+task to be run again. This removes the need to bump
+:term:`PR` values, and changes to metadata automatically
+ripple across the build.
+
+It is also worth noting that the end result of these signature
+generators is to make some dependency and hash information available to
+the build. This information includes:
+
+-  ``BB_BASEHASH_task-``\ *taskname*: The base hashes for each task in the
+   recipe.
+
+-  ``BB_BASEHASH_``\ *filename:taskname*: The base hashes for each
+   dependent task.
+
+-  ``BBHASHDEPS_``\ *filename:taskname*: The task dependencies for
+   each task.
+
+-  ``BB_TASKHASH``: The hash of the currently running task.
+
+It is worth noting that BitBake's "-S" option lets you debug BitBake's
+processing of signatures. The options passed to -S allow different
+debugging modes to be used, either using BitBake's own debug functions
+or possibly those defined in the metadata/signature handler itself. The
+simplest parameter to pass is "none", which causes a set of signature
+information to be written out into ``STAMPS_DIR`` corresponding to the
+targets specified. The other currently available parameter is
+"printdiff", which causes BitBake to try to establish the closest
+signature match it can (e.g. in the sstate cache) and then run
+``bitbake-diffsigs`` over the matches to determine the stamps and delta
+where these two stamp trees diverge.
+
+.. note::
+
+   It is likely that future versions of BitBake will provide other
+   signature handlers triggered through additional "-S" parameters.
+
+You can find more information on checksum metadata in the
+:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
+section.
+
+Setscene
+========
+
+The setscene process enables BitBake to handle "pre-built" artifacts.
+The ability to handle and reuse these artifacts allows BitBake the
+luxury of not having to build something from scratch every time.
+Instead, BitBake can use, when possible, existing build artifacts.
+
+BitBake needs to have reliable data indicating whether or not an
+artifact is compatible. Signatures, described in the previous section,
+provide an ideal way of representing whether an artifact is compatible.
+If a signature is the same, an object can be reused.
+
+If an object can be reused, the problem then becomes how to replace a
+given task or set of tasks with the pre-built artifact. BitBake solves
+the problem with the "setscene" process.
+
+When BitBake is asked to build a given target, before building anything,
+it first asks whether cached information is available for any of the
+targets it's building, or any of the intermediate targets. If cached
+information is available, BitBake uses this information instead of
+running the main tasks.
+
+BitBake first calls the function defined by the
+:term:`BB_HASHCHECK_FUNCTION` variable
+with a list of tasks and corresponding hashes it wants to build. This
+function is designed to be fast and returns a list of the tasks for
+which it believes in can obtain artifacts.
+
+Next, for each of the tasks that were returned as possibilities, BitBake
+executes a setscene version of the task that the possible artifact
+covers. Setscene versions of a task have the string "_setscene" appended
+to the task name. So, for example, the task with the name ``xxx`` has a
+setscene task named ``xxx_setscene``. The setscene version of the task
+executes and provides the necessary artifacts returning either success
+or failure.
+
+As previously mentioned, an artifact can cover more than one task. For
+example, it is pointless to obtain a compiler if you already have the
+compiled binary. To handle this, BitBake calls the
+:term:`BB_SETSCENE_DEPVALID` function for
+each successful setscene task to know whether or not it needs to obtain
+the dependencies of that task.
+
+Finally, after all the setscene tasks have executed, BitBake calls the
+function listed in
+:term:`BB_SETSCENE_VERIFY_FUNCTION2`
+with the list of tasks BitBake thinks has been "covered". The metadata
+can then ensure that this list is correct and can inform BitBake that it
+wants specific tasks to be run regardless of the setscene result.
+
+You can find more information on setscene metadata in the
+:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
+section.
+
+Logging
+=======
+
+In addition to the standard command line option to control how verbose
+builds are when execute, bitbake also supports user defined
+configuration of the `Python
+logging <https://docs.python.org/3/library/logging.html>`__ facilities
+through the :term:`BB_LOGCONFIG` variable. This
+variable defines a json or yaml `logging
+configuration <https://docs.python.org/3/library/logging.config.html>`__
+that will be intelligently merged into the default configuration. The
+logging configuration is merged using the following rules:
+
+-  The user defined configuration will completely replace the default
+   configuration if top level key ``bitbake_merge`` is set to the value
+   ``False``. In this case, all other rules are ignored.
+
+-  The user configuration must have a top level ``version`` which must
+   match the value of the default configuration.
+
+-  Any keys defined in the ``handlers``, ``formatters``, or ``filters``,
+   will be merged into the same section in the default configuration,
+   with the user specified keys taking replacing a default one if there
+   is a conflict. In practice, this means that if both the default
+   configuration and user configuration specify a handler named
+   ``myhandler``, the user defined one will replace the default. To
+   prevent the user from inadvertently replacing a default handler,
+   formatter, or filter, all of the default ones are named with a prefix
+   of "``BitBake.``"
+
+-  If a logger is defined by the user with the key ``bitbake_merge`` set
+   to ``False``, that logger will be completely replaced by user
+   configuration. In this case, no other rules will apply to that
+   logger.
+
+-  All user defined ``filter`` and ``handlers`` properties for a given
+   logger will be merged with corresponding properties from the default
+   logger. For example, if the user configuration adds a filter called
+   ``myFilter`` to the ``BitBake.SigGen``, and the default configuration
+   adds a filter called ``BitBake.defaultFilter``, both filters will be
+   applied to the logger
+
+As an example, consider the following user logging configuration file
+which logs all Hash Equivalence related messages of VERBOSE or higher to
+a file called ``hashequiv.log`` ::
+
+   {
+       "version": 1,
+       "handlers": {
+           "autobuilderlog": {
+               "class": "logging.FileHandler",
+               "formatter": "logfileFormatter",
+               "level": "DEBUG",
+               "filename": "hashequiv.log",
+               "mode": "w"
+           }
+       },
+       "formatters": {
+               "logfileFormatter": {
+                   "format": "%(name)s: %(levelname)s: %(message)s"
+               }
+       },
+       "loggers": {
+           "BitBake.SigGen.HashEquiv": {
+               "level": "VERBOSE",
+               "handlers": ["autobuilderlog"]
+           },
+           "BitBake.RunQueue.HashEquiv": {
+               "level": "VERBOSE",
+               "handlers": ["autobuilderlog"]
+           }
+       }
+   }
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
deleted file mode 100644
index e4251dff..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
+++ /dev/null
@@ -1,1029 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<chapter id="bitbake-user-manual-execution">
-    <title>Execution</title>
-
-    <para>
-        The primary purpose for running BitBake is to produce some kind
-        of output such as a single installable package, a kernel, a software
-        development kit, or even a full, board-specific bootable Linux image,
-        complete with bootloader, kernel, and root filesystem.
-        Of course, you can execute the <filename>bitbake</filename>
-        command with options that cause it to execute single tasks,
-        compile single recipe files, capture or clear data, or simply
-        return information about the execution environment.
-    </para>
-
-    <para>
-        This chapter describes BitBake's execution process from start
-        to finish when you use it to create an image.
-        The execution process is launched using the following command
-        form:
-        <literallayout class='monospaced'>
-     $ bitbake <replaceable>target</replaceable>
-        </literallayout>
-        For information on the BitBake command and its options,
-        see
-        "<link linkend='bitbake-user-manual-command'>The BitBake Command</link>"
-        section.
-        <note>
-            <para>
-                Prior to executing BitBake, you should take advantage of available
-                parallel thread execution on your build host by setting the
-                <link linkend='var-bb-BB_NUMBER_THREADS'><filename>BB_NUMBER_THREADS</filename></link>
-                variable in your project's <filename>local.conf</filename>
-                configuration file.
-            </para>
-
-            <para>
-                A common method to determine this value for your build host is to run
-                the following:
-                <literallayout class='monospaced'>
-     $ grep processor /proc/cpuinfo
-                </literallayout>
-                This command returns the number of processors, which takes into
-                account hyper-threading.
-                Thus, a quad-core build host with hyper-threading most likely
-                shows eight processors, which is the value you would then assign to
-                <filename>BB_NUMBER_THREADS</filename>.
-            </para>
-
-            <para>
-                A possibly simpler solution is that some Linux distributions
-                (e.g. Debian and Ubuntu) provide the <filename>ncpus</filename> command.
-            </para>
-        </note>
-    </para>
-
-    <section id='parsing-the-base-configuration-metadata'>
-        <title>Parsing the Base Configuration Metadata</title>
-
-        <para>
-            The first thing BitBake does is parse base configuration
-            metadata.
-            Base configuration metadata consists of your project's
-            <filename>bblayers.conf</filename> file to determine what
-            layers BitBake needs to recognize, all necessary
-            <filename>layer.conf</filename> files (one from each layer),
-            and <filename>bitbake.conf</filename>.
-            The data itself is of various types:
-            <itemizedlist>
-                <listitem><para><emphasis>Recipes:</emphasis>
-                    Details about particular pieces of software.
-                    </para></listitem>
-                <listitem><para><emphasis>Class Data:</emphasis>
-                    An abstraction of common build information
-                    (e.g. how to build a Linux kernel).
-                    </para></listitem>
-                <listitem><para><emphasis>Configuration Data:</emphasis>
-                    Machine-specific settings, policy decisions,
-                    and so forth.
-                    Configuration data acts as the glue to bind everything
-                    together.</para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            The <filename>layer.conf</filename> files are used to
-            construct key variables such as
-            <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
-            and
-            <link linkend='var-bb-BBFILES'><filename>BBFILES</filename></link>.
-            <filename>BBPATH</filename> is used to search for
-            configuration and class files under the
-            <filename>conf</filename> and <filename>classes</filename>
-            directories, respectively.
-            <filename>BBFILES</filename> is used to locate both recipe
-            and recipe append files
-            (<filename>.bb</filename> and <filename>.bbappend</filename>).
-            If there is no <filename>bblayers.conf</filename> file,
-            it is assumed the user has set the <filename>BBPATH</filename>
-            and <filename>BBFILES</filename> directly in the environment.
-        </para>
-
-        <para>
-            Next, the <filename>bitbake.conf</filename> file is located
-            using the <filename>BBPATH</filename> variable that was
-            just constructed.
-            The <filename>bitbake.conf</filename> file may also include other
-            configuration files using the
-            <filename>include</filename> or
-            <filename>require</filename> directives.
-        </para>
-
-        <para>
-            Prior to parsing configuration files, BitBake looks
-            at certain variables, including:
-            <itemizedlist>
-                <listitem><para>
-                    <link linkend='var-bb-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_ORIGENV'><filename>BB_ORIGENV</filename></link>
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BITBAKE_UI'><filename>BITBAKE_UI</filename></link>
-                    </para></listitem>
-            </itemizedlist>
-            The first four variables in this list relate to how BitBake treats shell
-            environment variables during task execution.
-            By default, BitBake cleans the environment variables and provides tight
-            control over the shell execution environment.
-            However, through the use of these first four variables, you can
-            apply your control regarding the
-            environment variables allowed to be used by BitBake in the shell
-            during execution of tasks.
-            See the
-            "<link linkend='passing-information-into-the-build-task-environment'>Passing Information Into the Build Task Environment</link>"
-            section and the information about these variables in the
-            variable glossary for more information on how they work and
-            on how to use them.
-        </para>
-
-        <para>
-            The base configuration metadata is global
-            and therefore affects all recipes and tasks that are executed.
-        </para>
-
-        <para>
-            BitBake first searches the current working directory for an
-            optional <filename>conf/bblayers.conf</filename> configuration file.
-            This file is expected to contain a
-            <link linkend='var-bb-BBLAYERS'><filename>BBLAYERS</filename></link>
-            variable that is a space-delimited list of 'layer' directories.
-            Recall that if BitBake cannot find a <filename>bblayers.conf</filename>
-            file, then it is assumed the user has set the <filename>BBPATH</filename>
-            and <filename>BBFILES</filename> variables directly in the environment.
-        </para>
-
-        <para>
-            For each directory (layer) in this list, a <filename>conf/layer.conf</filename>
-            file is located and parsed with the
-            <link linkend='var-bb-LAYERDIR'><filename>LAYERDIR</filename></link>
-            variable being set to the directory where the layer was found.
-            The idea is these files automatically set up
-            <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
-            and other variables correctly for a given build directory.
-        </para>
-
-        <para>
-            BitBake then expects to find the <filename>conf/bitbake.conf</filename>
-            file somewhere in the user-specified <filename>BBPATH</filename>.
-            That configuration file generally has include directives to pull
-            in any other metadata such as files specific to the architecture,
-            the machine, the local environment, and so forth.
-        </para>
-
-        <para>
-            Only variable definitions and include directives are allowed
-            in BitBake <filename>.conf</filename> files.
-            Some variables directly influence BitBake's behavior.
-            These variables might have been set from the environment
-            depending on the environment variables previously
-            mentioned or set in the configuration files.
-            The
-            "<link linkend='ref-bb-variables-glos'>Variables Glossary</link>"
-            chapter presents a full list of variables.
-        </para>
-
-        <para>
-            After parsing configuration files, BitBake uses its rudimentary
-            inheritance mechanism, which is through class files, to inherit
-            some standard classes.
-            BitBake parses a class when the inherit directive responsible
-            for getting that class is encountered.
-        </para>
-
-        <para>
-            The <filename>base.bbclass</filename> file is always included.
-            Other classes that are specified in the configuration using the
-            <link linkend='var-bb-INHERIT'><filename>INHERIT</filename></link>
-            variable are also included.
-            BitBake searches for class files in a
-            <filename>classes</filename> subdirectory under
-            the paths in <filename>BBPATH</filename> in the same way as
-            configuration files.
-        </para>
-
-        <para>
-            A good way to get an idea of the configuration files and
-            the class files used in your execution environment is to
-            run the following BitBake command:
-            <literallayout class='monospaced'>
-     $ bitbake -e > mybb.log
-            </literallayout>
-            Examining the top of the <filename>mybb.log</filename>
-            shows you the many configuration files and class files
-            used in your execution environment.
-        </para>
-
-        <note>
-            <para>
-                You need to be aware of how BitBake parses curly braces.
-                If a recipe uses a closing curly brace within the function and
-                the character has no leading spaces, BitBake produces a parsing
-                error.
-                If you use a pair of curly braces in a shell function, the
-                closing curly brace must not be located at the start of the line
-                without leading spaces.
-            </para>
-
-            <para>
-                Here is an example that causes BitBake to produce a parsing
-                error:
-                <literallayout class='monospaced'>
-     fakeroot create_shar() {
-         cat &lt;&lt; "EOF" &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
-     usage()
-     {
-       echo "test"
-       ###### The following "}" at the start of the line causes a parsing error ######
-     }
-     EOF
-     }
-                </literallayout>
-                Writing the recipe this way avoids the error:
-                <literallayout class='monospaced'>
-     fakeroot create_shar() {
-         cat &lt;&lt; "EOF" &gt; ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
-     usage()
-     {
-       echo "test"
-       ######The following "}" with a leading space at the start of the line avoids the error ######
-      }
-     EOF
-     }
-                </literallayout>
-            </para>
-        </note>
-    </section>
-
-    <section id='locating-and-parsing-recipes'>
-        <title>Locating and Parsing Recipes</title>
-
-        <para>
-            During the configuration phase, BitBake will have set
-            <link linkend='var-bb-BBFILES'><filename>BBFILES</filename></link>.
-            BitBake now uses it to construct a list of recipes to parse,
-            along with any append files (<filename>.bbappend</filename>)
-            to apply.
-            <filename>BBFILES</filename> is a space-separated list of
-            available files and supports wildcards.
-            An example would be:
-            <literallayout class='monospaced'>
-     BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"
-            </literallayout>
-            BitBake parses each recipe and append file located
-            with <filename>BBFILES</filename> and stores the values of
-            various variables into the datastore.
-            <note>
-                Append files are applied in the order they are encountered in
-                <filename>BBFILES</filename>.
-            </note>
-            For each file, a fresh copy of the base configuration is
-            made, then the recipe is parsed line by line.
-            Any inherit statements cause BitBake to find and
-            then parse class files (<filename>.bbclass</filename>)
-            using
-            <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
-            as the search path.
-            Finally, BitBake parses in order any append files found in
-            <filename>BBFILES</filename>.
-        </para>
-
-        <para>
-            One common convention is to use the recipe filename to define
-            pieces of metadata.
-            For example, in <filename>bitbake.conf</filename> the recipe
-            name and version are used to set the variables
-            <link linkend='var-bb-PN'><filename>PN</filename></link> and
-            <link linkend='var-bb-PV'><filename>PV</filename></link>:
-            <literallayout class='monospaced'>
-     PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
-     PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
-            </literallayout>
-            In this example, a recipe called "something_1.2.3.bb" would set
-            <filename>PN</filename> to "something" and
-            <filename>PV</filename> to "1.2.3".
-        </para>
-
-        <para>
-            By the time parsing is complete for a recipe, BitBake
-            has a list of tasks that the recipe defines and a set of
-            data consisting of keys and values as well as
-            dependency information about the tasks.
-        </para>
-
-        <para>
-            BitBake does not need all of this information.
-            It only needs a small subset of the information to make
-            decisions about the recipe.
-            Consequently, BitBake caches the values in which it is
-            interested and does not store the rest of the information.
-            Experience has shown it is faster to re-parse the metadata than to
-            try and write it out to the disk and then reload it.
-        </para>
-
-        <para>
-            Where possible, subsequent BitBake commands reuse this cache of
-            recipe information.
-            The validity of this cache is determined by first computing a
-            checksum of the base configuration data (see
-            <link linkend='var-bb-BB_HASHCONFIG_WHITELIST'><filename>BB_HASHCONFIG_WHITELIST</filename></link>)
-            and then checking if the checksum matches.
-            If that checksum matches what is in the cache and the recipe
-            and class files have not changed, BitBake is able to use
-            the cache.
-            BitBake then reloads the cached information about the recipe
-            instead of reparsing it from scratch.
-        </para>
-
-        <para>
-            Recipe file collections exist to allow the user to
-            have multiple repositories of
-            <filename>.bb</filename> files that contain the same
-            exact package.
-            For example, one could easily use them to make one's
-            own local copy of an upstream repository, but with
-            custom modifications that one does not want upstream.
-            Here is an example:
-            <literallayout class='monospaced'>
-    BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
-    BBFILE_COLLECTIONS = "upstream local"
-    BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
-    BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
-    BBFILE_PRIORITY_upstream = "5"
-    BBFILE_PRIORITY_local = "10"
-            </literallayout>
-            <note>
-                The layers mechanism is now the preferred method of collecting
-                code.
-                While the collections code remains, its main use is to set layer
-                priorities and to deal with overlap (conflicts) between layers.
-            </note>
-        </para>
-    </section>
-
-    <section id='bb-bitbake-providers'>
-        <title>Providers</title>
-
-        <para>
-            Assuming BitBake has been instructed to execute a target
-            and that all the recipe files have been parsed, BitBake
-            starts to figure out how to build the target.
-            BitBake looks through the <filename>PROVIDES</filename> list
-            for each of the recipes.
-            A <filename>PROVIDES</filename> list is the list of names by which
-            the recipe can be known.
-            Each recipe's <filename>PROVIDES</filename> list is created
-            implicitly through the recipe's
-            <link linkend='var-bb-PN'><filename>PN</filename></link> variable
-            and explicitly through the recipe's
-            <link linkend='var-bb-PROVIDES'><filename>PROVIDES</filename></link>
-            variable, which is optional.
-        </para>
-
-        <para>
-            When a recipe uses <filename>PROVIDES</filename>, that recipe's
-            functionality can be found under an alternative name or names other
-            than the implicit <filename>PN</filename> name.
-            As an example, suppose a recipe named <filename>keyboard_1.0.bb</filename>
-            contained the following:
-            <literallayout class='monospaced'>
-     PROVIDES += "fullkeyboard"
-            </literallayout>
-            The <filename>PROVIDES</filename> list for this recipe becomes
-            "keyboard", which is implicit, and "fullkeyboard", which is explicit.
-            Consequently, the functionality found in
-            <filename>keyboard_1.0.bb</filename> can be found under two
-            different names.
-        </para>
-    </section>
-
-    <section id='bb-bitbake-preferences'>
-        <title>Preferences</title>
-
-        <para>
-            The <filename>PROVIDES</filename> list is only part of the solution
-            for figuring out a target's recipes.
-            Because targets might have multiple providers, BitBake needs
-            to prioritize providers by determining provider preferences.
-        </para>
-
-        <para>
-            A common example in which a target has multiple providers
-            is "virtual/kernel", which is on the
-            <filename>PROVIDES</filename> list for each kernel recipe.
-            Each machine often selects the best kernel provider by using a
-            line similar to the following in the machine configuration file:
-            <literallayout class='monospaced'>
-     PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
-            </literallayout>
-            The default
-            <link linkend='var-bb-PREFERRED_PROVIDER'><filename>PREFERRED_PROVIDER</filename></link>
-            is the provider with the same name as the target.
-            BitBake iterates through each target it needs to build and
-            resolves them and their dependencies using this process.
-        </para>
-
-        <para>
-            Understanding how providers are chosen is made complicated by the fact
-            that multiple versions might exist for a given provider.
-            BitBake defaults to the highest version of a provider.
-            Version comparisons are made using the same method as Debian.
-            You can use the
-            <link linkend='var-bb-PREFERRED_VERSION'><filename>PREFERRED_VERSION</filename></link>
-            variable to specify a particular version.
-            You can influence the order by using the
-            <link linkend='var-bb-DEFAULT_PREFERENCE'><filename>DEFAULT_PREFERENCE</filename></link>
-            variable.
-        </para>
-
-        <para>
-            By default, files have a preference of "0".
-            Setting <filename>DEFAULT_PREFERENCE</filename> to "-1" makes the
-            recipe unlikely to be used unless it is explicitly referenced.
-            Setting <filename>DEFAULT_PREFERENCE</filename> to "1" makes it
-            likely the recipe is used.
-            <filename>PREFERRED_VERSION</filename> overrides any
-            <filename>DEFAULT_PREFERENCE</filename> setting.
-            <filename>DEFAULT_PREFERENCE</filename> is often used to mark newer
-            and more experimental recipe versions until they have undergone
-            sufficient testing to be considered stable.
-        </para>
-
-        <para>
-            When there are multiple “versions” of a given recipe,
-            BitBake defaults to selecting the most recent
-            version, unless otherwise specified.
-            If the recipe in question has a
-            <link linkend='var-bb-DEFAULT_PREFERENCE'><filename>DEFAULT_PREFERENCE</filename></link>
-            set lower than the other recipes (default is 0), then
-            it will not be selected.
-            This allows the person or persons maintaining
-            the repository of recipe files to specify
-            their preference for the default selected version.
-            Additionally, the user can specify their preferred version.
-        </para>
-
-        <para>
-            If the first recipe is named <filename>a_1.1.bb</filename>, then the
-            <link linkend='var-bb-PN'><filename>PN</filename></link> variable
-            will be set to “a”, and the
-            <link linkend='var-bb-PV'><filename>PV</filename></link>
-            variable will be set to 1.1.
-        </para>
-
-        <para>
-            Thus, if a recipe named <filename>a_1.2.bb</filename> exists, BitBake
-            will choose 1.2 by default.
-            However, if you define the following variable in a
-            <filename>.conf</filename> file that BitBake parses, you
-            can change that preference:
-            <literallayout class='monospaced'>
-     PREFERRED_VERSION_a = "1.1"
-            </literallayout>
-        </para>
-
-        <note>
-            <para>
-                It is common for a recipe to provide two versions -- a stable,
-                numbered (and preferred) version, and a version that is
-                automatically checked out from a source code repository that
-                is considered more "bleeding edge" but can be selected only
-                explicitly.
-            </para>
-
-            <para>
-                For example, in the OpenEmbedded codebase, there is a standard,
-                versioned recipe file for BusyBox,
-                <filename>busybox_1.22.1.bb</filename>,
-                but there is also a Git-based version,
-                <filename>busybox_git.bb</filename>, which explicitly contains the line
-                <literallayout class='monospaced'>
-    DEFAULT_PREFERENCE = "-1"
-                </literallayout>
-                to ensure that the numbered, stable version is always preferred
-                unless the developer selects otherwise.
-            </para>
-        </note>
-    </section>
-
-    <section id='bb-bitbake-dependencies'>
-        <title>Dependencies</title>
-
-        <para>
-            Each target BitBake builds consists of multiple tasks such as
-            <filename>fetch</filename>, <filename>unpack</filename>,
-            <filename>patch</filename>, <filename>configure</filename>,
-            and <filename>compile</filename>.
-            For best performance on multi-core systems, BitBake considers each
-            task as an independent
-            entity with its own set of dependencies.
-        </para>
-
-        <para>
-            Dependencies are defined through several variables.
-            You can find information about variables BitBake uses in
-            the <link linkend='ref-bb-variables-glos'>Variables Glossary</link>
-            near the end of this manual.
-            At a basic level, it is sufficient to know that BitBake uses the
-            <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link> and
-            <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link> variables when
-            calculating dependencies.
-        </para>
-
-        <para>
-            For more information on how BitBake handles dependencies, see the
-            "<link linkend='dependencies'>Dependencies</link>" section.
-        </para>
-    </section>
-
-    <section id='ref-bitbake-tasklist'>
-        <title>The Task List</title>
-
-        <para>
-            Based on the generated list of providers and the dependency information,
-            BitBake can now calculate exactly what tasks it needs to run and in what
-            order it needs to run them.
-            The
-            "<link linkend='executing-tasks'>Executing Tasks</link>" section has more
-            information on how BitBake chooses which task to execute next.
-        </para>
-
-        <para>
-            The build now starts with BitBake forking off threads up to the limit set in the
-            <link linkend='var-bb-BB_NUMBER_THREADS'><filename>BB_NUMBER_THREADS</filename></link>
-            variable.
-            BitBake continues to fork threads as long as there are tasks ready to run,
-            those tasks have all their dependencies met, and the thread threshold has not been
-            exceeded.
-        </para>
-
-        <para>
-            It is worth noting that you can greatly speed up the build time by properly setting
-            the <filename>BB_NUMBER_THREADS</filename> variable.
-        </para>
-
-        <para>
-            As each task completes, a timestamp is written to the directory specified by the
-            <link linkend='var-bb-STAMP'><filename>STAMP</filename></link> variable.
-            On subsequent runs, BitBake looks in the build directory within
-            <filename>tmp/stamps</filename> and does not rerun
-            tasks that are already completed unless a timestamp is found to be invalid.
-            Currently, invalid timestamps are only considered on a per
-            recipe file basis.
-            So, for example, if the configure stamp has a timestamp greater than the
-            compile timestamp for a given target, then the compile task would rerun.
-            Running the compile task again, however, has no effect on other providers
-            that depend on that target.
-        </para>
-
-        <para>
-            The exact format of the stamps is partly configurable.
-            In modern versions of BitBake, a hash is appended to the
-            stamp so that if the configuration changes, the stamp becomes
-            invalid and the task is automatically rerun.
-            This hash, or signature used, is governed by the signature policy
-            that is configured (see the
-            "<link linkend='checksums'>Checksums (Signatures)</link>"
-            section for information).
-            It is also possible to append extra metadata to the stamp using
-            the <filename>[stamp-extra-info]</filename> task flag.
-            For example, OpenEmbedded uses this flag to make some tasks machine-specific.
-        </para>
-
-        <note>
-            Some tasks are marked as "nostamp" tasks.
-            No timestamp file is created when these tasks are run.
-            Consequently, "nostamp" tasks are always rerun.
-        </note>
-
-        <para>
-            For more information on tasks, see the
-            "<link linkend='tasks'>Tasks</link>" section.
-        </para>
-    </section>
-
-    <section id='executing-tasks'>
-        <title>Executing Tasks</title>
-
-        <para>
-            Tasks can be either a shell task or a Python task.
-            For shell tasks, BitBake writes a shell script to
-            <filename>${</filename><link linkend='var-bb-T'><filename>T</filename></link><filename>}/run.do_taskname.<replaceable>pid</replaceable></filename>
-            and then executes the script.
-            The generated shell script contains all the exported variables,
-            and the shell functions with all variables expanded.
-            Output from the shell script goes to the file
-            <filename>${T}/log.do_taskname.<replaceable>pid</replaceable></filename>.
-            Looking at the expanded shell functions in the run file and
-            the output in the log files is a useful debugging technique.
-        </para>
-
-        <para>
-            For Python tasks, BitBake executes the task internally and logs
-            information to the controlling terminal.
-            Future versions of BitBake will write the functions to files
-            similar to the way shell tasks are handled.
-            Logging will be handled in a way similar to shell tasks as well.
-        </para>
-
-        <para>
-            The order in which BitBake runs the tasks is controlled by its
-            task scheduler.
-            It is possible to configure the scheduler and define custom
-            implementations for specific use cases.
-            For more information, see these variables that control the
-            behavior:
-            <itemizedlist>
-                <listitem><para>
-                    <link linkend='var-bb-BB_SCHEDULER'><filename>BB_SCHEDULER</filename></link>
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_SCHEDULERS'><filename>BB_SCHEDULERS</filename></link>
-                    </para></listitem>
-            </itemizedlist>
-            It is possible to have functions run before and after a task's main
-            function.
-            This is done using the <filename>[prefuncs]</filename>
-            and <filename>[postfuncs]</filename> flags of the task
-            that lists the functions to run.
-        </para>
-    </section>
-
-    <section id='checksums'>
-        <title>Checksums (Signatures)</title>
-
-        <para>
-            A checksum is a unique signature of a task's inputs.
-            The signature of a task can be used to determine if a task
-            needs to be run.
-            Because it is a change in a task's inputs that triggers running
-            the task, BitBake needs to detect all the inputs to a given task.
-            For shell tasks, this turns out to be fairly easy because
-            BitBake generates a "run" shell script for each task and
-            it is possible to create a checksum that gives you a good idea of when
-            the task's data changes.
-        </para>
-
-        <para>
-            To complicate the problem, some things should not be included in
-            the checksum.
-            First, there is the actual specific build path of a given task -
-            the working directory.
-            It does not matter if the working directory changes because it should not
-            affect the output for target packages.
-            The simplistic approach for excluding the working directory is to set
-            it to some fixed value and create the checksum for the "run" script.
-            BitBake goes one step better and uses the
-            <link linkend='var-bb-BB_HASHBASE_WHITELIST'><filename>BB_HASHBASE_WHITELIST</filename></link>
-            variable to define a list of variables that should never be included
-            when generating the signatures.
-        </para>
-
-        <para>
-            Another problem results from the "run" scripts containing functions that
-            might or might not get called.
-            The incremental build solution contains code that figures out dependencies
-            between shell functions.
-            This code is used to prune the "run" scripts down to the minimum set,
-            thereby alleviating this problem and making the "run" scripts much more
-            readable as a bonus.
-        </para>
-
-        <para>
-            So far we have solutions for shell scripts.
-            What about Python tasks?
-            The same approach applies even though these tasks are more difficult.
-            The process needs to figure out what variables a Python function accesses
-            and what functions it calls.
-            Again, the incremental build solution contains code that first figures out
-            the variable and function dependencies, and then creates a checksum for the data
-            used as the input to the task.
-        </para>
-
-        <para>
-            Like the working directory case, situations exist where dependencies
-            should be ignored.
-            For these cases, you can instruct the build process to ignore a dependency
-            by using a line like the following:
-            <literallayout class='monospaced'>
-     PACKAGE_ARCHS[vardepsexclude] = "MACHINE"
-            </literallayout>
-            This example ensures that the <filename>PACKAGE_ARCHS</filename> variable does not
-            depend on the value of <filename>MACHINE</filename>, even if it does reference it.
-        </para>
-
-        <para>
-            Equally, there are cases where we need to add dependencies BitBake
-            is not able to find.
-            You can accomplish this by using a line like the following:
-            <literallayout class='monospaced'>
-      PACKAGE_ARCHS[vardeps] = "MACHINE"
-            </literallayout>
-            This example explicitly adds the <filename>MACHINE</filename> variable as a
-            dependency for <filename>PACKAGE_ARCHS</filename>.
-        </para>
-
-        <para>
-            Consider a case with in-line Python, for example, where BitBake is not
-            able to figure out dependencies.
-            When running in debug mode (i.e. using <filename>-DDD</filename>), BitBake
-            produces output when it discovers something for which it cannot figure out
-            dependencies.
-        </para>
-
-        <para>
-            Thus far, this section has limited discussion to the direct inputs into a task.
-            Information based on direct inputs is referred to as the "basehash" in the
-            code.
-            However, there is still the question of a task's indirect inputs - the
-            things that were already built and present in the build directory.
-            The checksum (or signature) for a particular task needs to add the hashes
-            of all the tasks on which the particular task depends.
-            Choosing which dependencies to add is a policy decision.
-            However, the effect is to generate a master checksum that combines the basehash
-            and the hashes of the task's dependencies.
-        </para>
-
-        <para>
-            At the code level, there are a variety of ways both the basehash and the
-            dependent task hashes can be influenced.
-            Within the BitBake configuration file, we can give BitBake some extra information
-            to help it construct the basehash.
-            The following statement effectively results in a list of global variable
-            dependency excludes - variables never included in any checksum.
-            This example uses variables from OpenEmbedded to help illustrate
-            the concept:
-            <literallayout class='monospaced'>
-     BB_HASHBASE_WHITELIST ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
-         SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL TERM \
-         USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
-         PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
-         CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"
-            </literallayout>
-            The previous example excludes the work directory, which is part of
-            <filename>TMPDIR</filename>.
-        </para>
-
-        <para>
-            The rules for deciding which hashes of dependent tasks to include through
-            dependency chains are more complex and are generally accomplished with a
-            Python function.
-            The code in <filename>meta/lib/oe/sstatesig.py</filename> shows two examples
-            of this and also illustrates how you can insert your own policy into the system
-            if so desired.
-            This file defines the two basic signature generators OpenEmbedded-Core
-            uses:  "OEBasic" and "OEBasicHash".
-            By default, there is a dummy "noop" signature handler enabled in BitBake.
-            This means that behavior is unchanged from previous versions.
-            <filename>OE-Core</filename> uses the "OEBasicHash" signature handler by default
-            through this setting in the <filename>bitbake.conf</filename> file:
-            <literallayout class='monospaced'>
-     BB_SIGNATURE_HANDLER ?= "OEBasicHash"
-            </literallayout>
-            The "OEBasicHash" <filename>BB_SIGNATURE_HANDLER</filename> is the same as the
-            "OEBasic" version but adds the task hash to the stamp files.
-            This results in any metadata change that changes the task hash, automatically
-            causing the task to be run again.
-            This removes the need to bump
-            <link linkend='var-bb-PR'><filename>PR</filename></link>
-            values, and changes to metadata automatically ripple across the build.
-        </para>
-
-        <para>
-            It is also worth noting that the end result of these signature generators is to
-            make some dependency and hash information available to the build.
-            This information includes:
-            <itemizedlist>
-                <listitem><para><filename>BB_BASEHASH_task-</filename><replaceable>taskname</replaceable>:
-                    The base hashes for each task in the recipe.
-                    </para></listitem>
-                <listitem><para><filename>BB_BASEHASH_</filename><replaceable>filename</replaceable><filename>:</filename><replaceable>taskname</replaceable>:
-                    The base hashes for each dependent task.
-                    </para></listitem>
-                <listitem><para><filename>BBHASHDEPS_</filename><replaceable>filename</replaceable><filename>:</filename><replaceable>taskname</replaceable>:
-                    The task dependencies for each task.
-                    </para></listitem>
-                <listitem><para><filename>BB_TASKHASH</filename>:
-                    The hash of the currently running task.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            It is worth noting that BitBake's "-S" option lets you
-            debug BitBake's processing of signatures.
-            The options passed to -S allow different debugging modes
-            to be used, either using BitBake's own debug functions
-            or possibly those defined in the metadata/signature handler
-            itself.
-            The simplest parameter to pass is "none", which causes a
-            set of signature information to be written out into
-            <filename>STAMPS_DIR</filename>
-            corresponding to the targets specified.
-            The other currently available parameter is "printdiff",
-            which causes BitBake to try to establish the closest
-            signature match it can (e.g. in the sstate cache) and then
-            run <filename>bitbake-diffsigs</filename> over the matches
-            to determine the stamps and delta where these two
-            stamp trees diverge.
-            <note>
-                It is likely that future versions of BitBake will
-                provide other signature handlers triggered through
-                additional "-S" parameters.
-            </note>
-        </para>
-
-        <para>
-            You can find more information on checksum metadata in the
-            "<link linkend='task-checksums-and-setscene'>Task Checksums and Setscene</link>"
-            section.
-        </para>
-    </section>
-
-    <section id='setscene'>
-        <title>Setscene</title>
-
-        <para>
-            The setscene process enables BitBake to handle "pre-built" artifacts.
-            The ability to handle and reuse these artifacts allows BitBake
-            the luxury of not having to build something from scratch every time.
-            Instead, BitBake can use, when possible, existing build artifacts.
-        </para>
-
-        <para>
-            BitBake needs to have reliable data indicating whether or not an
-            artifact is compatible.
-            Signatures, described in the previous section, provide an ideal
-            way of representing whether an artifact is compatible.
-            If a signature is the same, an object can be reused.
-        </para>
-
-        <para>
-            If an object can be reused, the problem then becomes how to
-            replace a given task or set of tasks with the pre-built artifact.
-            BitBake solves the problem with the "setscene" process.
-        </para>
-
-        <para>
-            When BitBake is asked to build a given target, before building anything,
-            it first asks whether cached information is available for any of the
-            targets it's building, or any of the intermediate targets.
-            If cached information is available, BitBake uses this information instead of
-            running the main tasks.
-        </para>
-
-        <para>
-            BitBake first calls the function defined by the
-            <link linkend='var-bb-BB_HASHCHECK_FUNCTION'><filename>BB_HASHCHECK_FUNCTION</filename></link>
-            variable with a list of tasks and corresponding
-            hashes it wants to build.
-            This function is designed to be fast and returns a list
-            of the tasks for which it believes in can obtain artifacts.
-        </para>
-
-        <para>
-            Next, for each of the tasks that were returned as possibilities,
-            BitBake executes a setscene version of the task that the possible
-            artifact covers.
-            Setscene versions of a task have the string "_setscene" appended to the
-            task name.
-            So, for example, the task with the name <filename>xxx</filename> has
-            a setscene task named <filename>xxx_setscene</filename>.
-            The setscene version of the task executes and provides the necessary
-            artifacts returning either success or failure.
-        </para>
-
-        <para>
-            As previously mentioned, an artifact can cover more than one task.
-            For example, it is pointless to obtain a compiler if you
-            already have the compiled binary.
-            To handle this, BitBake calls the
-            <link linkend='var-bb-BB_SETSCENE_DEPVALID'><filename>BB_SETSCENE_DEPVALID</filename></link>
-            function for each successful setscene task to know whether or not it needs
-            to obtain the dependencies of that task.
-        </para>
-
-        <para>
-            Finally, after all the setscene tasks have executed, BitBake calls the
-            function listed in
-            <link linkend='var-bb-BB_SETSCENE_VERIFY_FUNCTION2'><filename>BB_SETSCENE_VERIFY_FUNCTION2</filename></link>
-            with the list of tasks BitBake thinks has been "covered".
-            The metadata can then ensure that this list is correct and can
-            inform BitBake that it wants specific tasks to be run regardless
-            of the setscene result.
-        </para>
-
-        <para>
-            You can find more information on setscene metadata in the
-            "<link linkend='task-checksums-and-setscene'>Task Checksums and Setscene</link>"
-            section.
-        </para>
-    </section>
-
-    <section id="logging">
-        <title>Logging</title>
-        <para>
-            In addition to the standard command line option to control how
-            verbose builds are when execute, bitbake also supports user defined
-            configuration of the
-            <ulink url='https://docs.python.org/3/library/logging.html'>Python logging</ulink>
-            facilities through the
-            <link linkend="var-bb-BB_LOGCONFIG"><filename>BB_LOGCONFIG</filename></link>
-            variable. This variable defines a json or yaml
-            <ulink url='https://docs.python.org/3/library/logging.config.html'>logging configuration</ulink>
-            that will be intelligently merged into the default configuration.
-            The logging configuration is merged using the following rules:
-            <itemizedlist>
-                <listitem><para>
-                    The user defined configuration will completely replace the default
-                    configuration if top level key
-                    <filename>bitbake_merge</filename> is set to the value
-                    <filename>False</filename>. In this case, all other rules
-                    are ignored.
-                </para></listitem>
-                <listitem><para>
-                    The user configuration must have a top level
-                    <filename>version</filename> which must match the value of
-                    the default configuration.
-                </para></listitem>
-                <listitem><para>
-                    Any keys defined in the <filename>handlers</filename>,
-                    <filename>formatters</filename>, or <filename>filters</filename>,
-                    will be merged into the same section in the default
-                    configuration, with the user specified keys taking
-                    replacing a default one if there is a conflict. In
-                    practice, this means that if both the default configuration
-                    and user configuration specify a handler named
-                    <filename>myhandler</filename>, the user defined one will
-                    replace the default. To prevent the user from inadvertently
-                    replacing a default handler, formatter, or filter, all of
-                    the default ones are named with a prefix of
-                    "<filename>BitBake.</filename>"
-                </para></listitem>
-                <listitem><para>
-                    If a logger is defined by the user with the key
-                    <filename>bitbake_merge</filename> set to
-                    <filename>False</filename>, that logger will be completely
-                    replaced by user configuration. In this case, no other
-                    rules will apply to that logger.
-                </para></listitem>
-                <listitem><para>
-                    All user defined <filename>filter</filename> and
-                    <filename>handlers</filename> properties for a given logger
-                    will be merged with corresponding properties from the
-                    default logger. For example, if the user configuration adds
-                    a filter called <filename>myFilter</filename> to the
-                    <filename>BitBake.SigGen</filename>, and the default
-                    configuration adds a filter called
-                    <filename>BitBake.defaultFilter</filename>, both filters
-                    will be applied to the logger
-                </para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            As an example, consider the following user logging configuration
-            file which logs all Hash Equivalence related messages of VERBOSE or
-            higher to a file called <filename>hashequiv.log</filename>
-            <literallayout class='monospaced'>
-    {
-        "version": 1,
-        "handlers": {
-            "autobuilderlog": {
-                "class": "logging.FileHandler",
-                "formatter": "logfileFormatter",
-                "level": "DEBUG",
-                "filename": "hashequiv.log",
-                "mode": "w"
-            }
-        },
-        "formatters": {
-                "logfileFormatter": {
-                    "format": "%(name)s: %(levelname)s: %(message)s"
-                }
-        },
-        "loggers": {
-            "BitBake.SigGen.HashEquiv": {
-                "level": "VERBOSE",
-                "handlers": ["autobuilderlog"]
-            },
-            "BitBake.RunQueue.HashEquiv": {
-                "level": "VERBOSE",
-                "handlers": ["autobuilderlog"]
-            }
-        }
-    }
-            </literallayout>
-        </para>
-    </section>
-</chapter>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst
new file mode 100644
index 00000000..bd6cc0ef
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.rst
@@ -0,0 +1,689 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+=====================
+File Download Support
+=====================
+
+|
+
+BitBake's fetch module is a standalone piece of library code that deals
+with the intricacies of downloading source code and files from remote
+systems. Fetching source code is one of the cornerstones of building
+software. As such, this module forms an important part of BitBake.
+
+The current fetch module is called "fetch2" and refers to the fact that
+it is the second major version of the API. The original version is
+obsolete and has been removed from the codebase. Thus, in all cases,
+"fetch" refers to "fetch2" in this manual.
+
+The Download (Fetch)
+====================
+
+BitBake takes several steps when fetching source code or files. The
+fetcher codebase deals with two distinct processes in order: obtaining
+the files from somewhere (cached or otherwise) and then unpacking those
+files into a specific location and perhaps in a specific way. Getting
+and unpacking the files is often optionally followed by patching.
+Patching, however, is not covered by this module.
+
+The code to execute the first part of this process, a fetch, looks
+something like the following: ::
+
+   src_uri = (d.getVar('SRC_URI') or "").split()
+   fetcher = bb.fetch2.Fetch(src_uri, d)
+   fetcher.download()
+
+This code sets up an instance of the fetch class. The instance uses a
+space-separated list of URLs from the :term:`SRC_URI`
+variable and then calls the ``download`` method to download the files.
+
+The instantiation of the fetch class is usually followed by: ::
+
+   rootdir = l.getVar('WORKDIR')
+   fetcher.unpack(rootdir)
+
+This code unpacks the downloaded files to the specified by ``WORKDIR``.
+
+.. note::
+
+   For convenience, the naming in these examples matches the variables
+   used by OpenEmbedded. If you want to see the above code in action,
+   examine the OpenEmbedded class file ``base.bbclass``
+   .
+
+The ``SRC_URI`` and ``WORKDIR`` variables are not hardcoded into the
+fetcher, since those fetcher methods can be (and are) called with
+different variable names. In OpenEmbedded for example, the shared state
+(sstate) code uses the fetch module to fetch the sstate files.
+
+When the ``download()`` method is called, BitBake tries to resolve the
+URLs by looking for source files in a specific search order:
+
+-  *Pre-mirror Sites:* BitBake first uses pre-mirrors to try and find
+   source files. These locations are defined using the
+   :term:`PREMIRRORS` variable.
+
+-  *Source URI:* If pre-mirrors fail, BitBake uses the original URL (e.g
+   from ``SRC_URI``).
+
+-  *Mirror Sites:* If fetch failures occur, BitBake next uses mirror
+   locations as defined by the :term:`MIRRORS` variable.
+
+For each URL passed to the fetcher, the fetcher calls the submodule that
+handles that particular URL type. This behavior can be the source of
+some confusion when you are providing URLs for the ``SRC_URI`` variable.
+Consider the following two URLs: ::
+
+   http://git.yoctoproject.org/git/poky;protocol=git
+   git://git.yoctoproject.org/git/poky;protocol=http
+
+In the former case, the URL is passed to the ``wget`` fetcher, which does not
+understand "git". Therefore, the latter case is the correct form since the Git
+fetcher does know how to use HTTP as a transport.
+
+Here are some examples that show commonly used mirror definitions: ::
+
+   PREMIRRORS ?= "\
+      bzr://.*/.\*  http://somemirror.org/sources/ \\n \
+      cvs://.*/.\*  http://somemirror.org/sources/ \\n \
+      git://.*/.\*  http://somemirror.org/sources/ \\n \
+      hg://.*/.\*   http://somemirror.org/sources/ \\n \
+      osc://.*/.\*  http://somemirror.org/sources/ \\n \
+      p4://.*/.\*   http://somemirror.org/sources/ \\n \
+     svn://.*/.\*   http://somemirror.org/sources/ \\n"
+
+   MIRRORS =+ "\
+      ftp://.*/.\*   http://somemirror.org/sources/ \\n \
+      http://.*/.\*  http://somemirror.org/sources/ \\n \
+      https://.*/.\* http://somemirror.org/sources/ \\n"
+
+It is useful to note that BitBake
+supports cross-URLs. It is possible to mirror a Git repository on an
+HTTP server as a tarball. This is what the ``git://`` mapping in the
+previous example does.
+
+Since network accesses are slow, BitBake maintains a cache of files
+downloaded from the network. Any source files that are not local (i.e.
+downloaded from the Internet) are placed into the download directory,
+which is specified by the :term:`DL_DIR` variable.
+
+File integrity is of key importance for reproducing builds. For
+non-local archive downloads, the fetcher code can verify SHA-256 and MD5
+checksums to ensure the archives have been downloaded correctly. You can
+specify these checksums by using the ``SRC_URI`` variable with the
+appropriate varflags as follows: ::
+
+   SRC_URI[md5sum] = "value"
+   SRC_URI[sha256sum] = "value"
+
+You can also specify the checksums as
+parameters on the ``SRC_URI`` as shown below: ::
+
+  SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"
+
+If multiple URIs exist, you can specify the checksums either directly as
+in the previous example, or you can name the URLs. The following syntax
+shows how you name the URIs: ::
+
+   SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
+   SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d
+
+After a file has been downloaded and
+has had its checksum checked, a ".done" stamp is placed in ``DL_DIR``.
+BitBake uses this stamp during subsequent builds to avoid downloading or
+comparing a checksum for the file again.
+
+.. note::
+
+   It is assumed that local storage is safe from data corruption. If
+   this were not the case, there would be bigger issues to worry about.
+
+If :term:`BB_STRICT_CHECKSUM` is set, any
+download without a checksum triggers an error message. The
+:term:`BB_NO_NETWORK` variable can be used to
+make any attempted network access a fatal error, which is useful for
+checking that mirrors are complete as well as other things.
+
+.. _bb-the-unpack:
+
+The Unpack
+==========
+
+The unpack process usually immediately follows the download. For all
+URLs except Git URLs, BitBake uses the common ``unpack`` method.
+
+A number of parameters exist that you can specify within the URL to
+govern the behavior of the unpack stage:
+
+-  *unpack:* Controls whether the URL components are unpacked. If set to
+   "1", which is the default, the components are unpacked. If set to
+   "0", the unpack stage leaves the file alone. This parameter is useful
+   when you want an archive to be copied in and not be unpacked.
+
+-  *dos:* Applies to ``.zip`` and ``.jar`` files and specifies whether
+   to use DOS line ending conversion on text files.
+
+-  *basepath:* Instructs the unpack stage to strip the specified
+   directories from the source path when unpacking.
+
+-  *subdir:* Unpacks the specific URL to the specified subdirectory
+   within the root directory.
+
+The unpack call automatically decompresses and extracts files with ".Z",
+".z", ".gz", ".xz", ".zip", ".jar", ".ipk", ".rpm". ".srpm", ".deb" and
+".bz2" extensions as well as various combinations of tarball extensions.
+
+As mentioned, the Git fetcher has its own unpack method that is
+optimized to work with Git trees. Basically, this method works by
+cloning the tree into the final directory. The process is completed
+using references so that there is only one central copy of the Git
+metadata needed.
+
+.. _bb-fetchers:
+
+Fetchers
+========
+
+As mentioned earlier, the URL prefix determines which fetcher submodule
+BitBake uses. Each submodule can support different URL parameters, which
+are described in the following sections.
+
+.. _local-file-fetcher:
+
+Local file fetcher (``file://``)
+--------------------------------
+
+This submodule handles URLs that begin with ``file://``. The filename
+you specify within the URL can be either an absolute or relative path to
+a file. If the filename is relative, the contents of the
+:term:`FILESPATH` variable is used in the same way
+``PATH`` is used to find executables. If the file cannot be found, it is
+assumed that it is available in :term:`DL_DIR` by the
+time the ``download()`` method is called.
+
+If you specify a directory, the entire directory is unpacked.
+
+Here are a couple of example URLs, the first relative and the second
+absolute: ::
+
+   SRC_URI = "file://relativefile.patch"
+   SRC_URI = "file:///Users/ich/very_important_software"
+
+.. _http-ftp-fetcher:
+
+HTTP/FTP wget fetcher (``http://``, ``ftp://``, ``https://``)
+-------------------------------------------------------------
+
+This fetcher obtains files from web and FTP servers. Internally, the
+fetcher uses the wget utility.
+
+The executable and parameters used are specified by the
+``FETCHCMD_wget`` variable, which defaults to sensible values. The
+fetcher supports a parameter "downloadfilename" that allows the name of
+the downloaded file to be specified. Specifying the name of the
+downloaded file is useful for avoiding collisions in
+:term:`DL_DIR` when dealing with multiple files that
+have the same name.
+
+Some example URLs are as follows: ::
+
+   SRC_URI = "http://oe.handhelds.org/not_there.aac"
+   SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
+   SRC_URI = "ftp://you@oe.handhelds.org/home/you/secret.plan"
+
+.. note::
+
+   Because URL parameters are delimited by semi-colons, this can
+   introduce ambiguity when parsing URLs that also contain semi-colons,
+   for example:
+   ::
+
+           SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git;a=snapshot;h=a5dd47"
+
+
+   Such URLs should should be modified by replacing semi-colons with '&'
+   characters:
+   ::
+
+           SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47"
+
+
+   In most cases this should work. Treating semi-colons and '&' in
+   queries identically is recommended by the World Wide Web Consortium
+   (W3C). Note that due to the nature of the URL, you may have to
+   specify the name of the downloaded file as well:
+   ::
+
+           SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47;downloadfilename=myfile.bz2"
+
+
+.. _cvs-fetcher:
+
+CVS fetcher (``(cvs://``)
+-------------------------
+
+This submodule handles checking out files from the CVS version control
+system. You can configure it using a number of different variables:
+
+-  :term:`FETCHCMD_cvs <FETCHCMD>`: The name of the executable to use when running
+   the ``cvs`` command. This name is usually "cvs".
+
+-  :term:`SRCDATE`: The date to use when fetching the CVS source code. A
+   special value of "now" causes the checkout to be updated on every
+   build.
+
+-  :term:`CVSDIR`: Specifies where a temporary
+   checkout is saved. The location is often ``DL_DIR/cvs``.
+
+-  CVS_PROXY_HOST: The name to use as a "proxy=" parameter to the
+   ``cvs`` command.
+
+-  CVS_PROXY_PORT: The port number to use as a "proxyport="
+   parameter to the ``cvs`` command.
+
+As well as the standard username and password URL syntax, you can also
+configure the fetcher with various URL parameters:
+
+The supported parameters are as follows:
+
+-  *"method":* The protocol over which to communicate with the CVS
+   server. By default, this protocol is "pserver". If "method" is set to
+   "ext", BitBake examines the "rsh" parameter and sets ``CVS_RSH``. You
+   can use "dir" for local directories.
+
+-  *"module":* Specifies the module to check out. You must supply this
+   parameter.
+
+-  *"tag":* Describes which CVS TAG should be used for the checkout. By
+   default, the TAG is empty.
+
+-  *"date":* Specifies a date. If no "date" is specified, the
+   :term:`SRCDATE` of the configuration is used to
+   checkout a specific date. The special value of "now" causes the
+   checkout to be updated on every build.
+
+-  *"localdir":* Used to rename the module. Effectively, you are
+   renaming the output directory to which the module is unpacked. You
+   are forcing the module into a special directory relative to
+   :term:`CVSDIR`.
+
+-  *"rsh":* Used in conjunction with the "method" parameter.
+
+-  *"scmdata":* Causes the CVS metadata to be maintained in the tarball
+   the fetcher creates when set to "keep". The tarball is expanded into
+   the work directory. By default, the CVS metadata is removed.
+
+-  *"fullpath":* Controls whether the resulting checkout is at the
+   module level, which is the default, or is at deeper paths.
+
+-  *"norecurse":* Causes the fetcher to only checkout the specified
+   directory with no recurse into any subdirectories.
+
+-  *"port":* The port to which the CVS server connects.
+
+Some example URLs are as follows: ::
+
+   SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
+   SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
+
+.. _svn-fetcher:
+
+Subversion (SVN) Fetcher (``svn://``)
+-------------------------------------
+
+This fetcher submodule fetches code from the Subversion source control
+system. The executable used is specified by ``FETCHCMD_svn``, which
+defaults to "svn". The fetcher's temporary working directory is set by
+:term:`SVNDIR`, which is usually ``DL_DIR/svn``.
+
+The supported parameters are as follows:
+
+-  *"module":* The name of the svn module to checkout. You must provide
+   this parameter. You can think of this parameter as the top-level
+   directory of the repository data you want.
+
+-  *"path_spec":* A specific directory in which to checkout the
+   specified svn module.
+
+-  *"protocol":* The protocol to use, which defaults to "svn". If
+   "protocol" is set to "svn+ssh", the "ssh" parameter is also used.
+
+-  *"rev":* The revision of the source code to checkout.
+
+-  *"scmdata":* Causes the ".svn" directories to be available during
+   compile-time when set to "keep". By default, these directories are
+   removed.
+
+-  *"ssh":* An optional parameter used when "protocol" is set to
+   "svn+ssh". You can use this parameter to specify the ssh program used
+   by svn.
+
+-  *"transportuser":* When required, sets the username for the
+   transport. By default, this parameter is empty. The transport
+   username is different than the username used in the main URL, which
+   is passed to the subversion command.
+
+Following are three examples using svn: ::
+
+   SRC_URI = "svn://myrepos/proj1;module=vip;protocol=http;rev=667"
+   SRC_URI = "svn://myrepos/proj1;module=opie;protocol=svn+ssh"
+   SRC_URI = "svn://myrepos/proj1;module=trunk;protocol=http;path_spec=${MY_DIR}/proj1"
+
+.. _git-fetcher:
+
+Git Fetcher (``git://``)
+------------------------
+
+This fetcher submodule fetches code from the Git source control system.
+The fetcher works by creating a bare clone of the remote into
+:term:`GITDIR`, which is usually ``DL_DIR/git2``. This
+bare clone is then cloned into the work directory during the unpack
+stage when a specific tree is checked out. This is done using alternates
+and by reference to minimize the amount of duplicate data on the disk
+and make the unpack process fast. The executable used can be set with
+``FETCHCMD_git``.
+
+This fetcher supports the following parameters:
+
+-  *"protocol":* The protocol used to fetch the files. The default is
+   "git" when a hostname is set. If a hostname is not set, the Git
+   protocol is "file". You can also use "http", "https", "ssh" and
+   "rsync".
+
+-  *"nocheckout":* Tells the fetcher to not checkout source code when
+   unpacking when set to "1". Set this option for the URL where there is
+   a custom routine to checkout code. The default is "0".
+
+-  *"rebaseable":* Indicates that the upstream Git repository can be
+   rebased. You should set this parameter to "1" if revisions can become
+   detached from branches. In this case, the source mirror tarball is
+   done per revision, which has a loss of efficiency. Rebasing the
+   upstream Git repository could cause the current revision to disappear
+   from the upstream repository. This option reminds the fetcher to
+   preserve the local cache carefully for future use. The default value
+   for this parameter is "0".
+
+-  *"nobranch":* Tells the fetcher to not check the SHA validation for
+   the branch when set to "1". The default is "0". Set this option for
+   the recipe that refers to the commit that is valid for a tag instead
+   of the branch.
+
+-  *"bareclone":* Tells the fetcher to clone a bare clone into the
+   destination directory without checking out a working tree. Only the
+   raw Git metadata is provided. This parameter implies the "nocheckout"
+   parameter as well.
+
+-  *"branch":* The branch(es) of the Git tree to clone. If unset, this
+   is assumed to be "master". The number of branch parameters much match
+   the number of name parameters.
+
+-  *"rev":* The revision to use for the checkout. The default is
+   "master".
+
+-  *"tag":* Specifies a tag to use for the checkout. To correctly
+   resolve tags, BitBake must access the network. For that reason, tags
+   are often not used. As far as Git is concerned, the "tag" parameter
+   behaves effectively the same as the "rev" parameter.
+
+-  *"subpath":* Limits the checkout to a specific subpath of the tree.
+   By default, the whole tree is checked out.
+
+-  *"destsuffix":* The name of the path in which to place the checkout.
+   By default, the path is ``git/``.
+
+-  *"usehead":* Enables local ``git://`` URLs to use the current branch
+   HEAD as the revision for use with ``AUTOREV``. The "usehead"
+   parameter implies no branch and only works when the transfer protocol
+   is ``file://``.
+
+Here are some example URLs: ::
+
+   SRC_URI = "git://git.oe.handhelds.org/git/vip.git;tag=version-1"
+   SRC_URI = "git://git.oe.handhelds.org/git/vip.git;protocol=http"
+
+.. note::
+
+   Specifying passwords directly in ``git://`` urls is not supported.
+   There are several reasons: ``SRC_URI`` is often written out to logs and
+   other places, and that could easily leak passwords; it is also all too
+   easy to share metadata without removing passwords. SSH keys, ``~/.netrc``
+   and ``~/.ssh/config`` files can be used as alternatives.
+
+
+.. _gitsm-fetcher:
+
+Git Submodule Fetcher (``gitsm://``)
+------------------------------------
+
+This fetcher submodule inherits from the :ref:`Git
+fetcher<bitbake-user-manual/bitbake-user-manual-fetching:git fetcher
+(\`\`git://\`\`)>` and extends that fetcher's behavior by fetching a
+repository's submodules. :term:`SRC_URI` is passed to the Git fetcher as
+described in the :ref:`bitbake-user-manual/bitbake-user-manual-fetching:git
+fetcher (\`\`git://\`\`)` section.
+
+.. note::
+
+   You must clean a recipe when switching between '``git://``' and
+   '``gitsm://``' URLs.
+
+   The Git Submodules fetcher is not a complete fetcher implementation.
+   The fetcher has known issues where it does not use the normal source
+   mirroring infrastructure properly. Further, the submodule sources it
+   fetches are not visible to the licensing and source archiving
+   infrastructures.
+
+.. _clearcase-fetcher:
+
+ClearCase Fetcher (``ccrc://``)
+-------------------------------
+
+This fetcher submodule fetches code from a
+`ClearCase <http://en.wikipedia.org/wiki/Rational_ClearCase>`__
+repository.
+
+To use this fetcher, make sure your recipe has proper
+:term:`SRC_URI`, :term:`SRCREV`, and
+:term:`PV` settings. Here is an example: ::
+
+   SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
+   SRCREV = "EXAMPLE_CLEARCASE_TAG"
+   PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
+
+The fetcher uses the ``rcleartool`` or
+``cleartool`` remote client, depending on which one is available.
+
+Following are options for the ``SRC_URI`` statement:
+
+-  *vob*: The name, which must include the prepending "/" character,
+   of the ClearCase VOB. This option is required.
+
+-  *module*: The module, which must include the prepending "/"
+   character, in the selected VOB.
+
+   .. note::
+
+      The module and vob options are combined to create the load rule in the
+      view config spec. As an example, consider the vob and module values from
+      the SRC_URI statement at the start of this section. Combining those values
+      results in the following: ::
+
+         load /example_vob/example_module
+
+-  *proto*: The protocol, which can be either ``http`` or ``https``.
+
+By default, the fetcher creates a configuration specification. If you
+want this specification written to an area other than the default, use
+the ``CCASE_CUSTOM_CONFIG_SPEC`` variable in your recipe to define where
+the specification is written.
+
+.. note::
+
+   the SRCREV loses its functionality if you specify this variable. However,
+   SRCREV is still used to label the archive after a fetch even though it does
+   not define what is fetched.
+
+Here are a couple of other behaviors worth mentioning:
+
+-  When using ``cleartool``, the login of ``cleartool`` is handled by
+   the system. The login require no special steps.
+
+-  In order to use ``rcleartool`` with authenticated users, an
+   "rcleartool login" is necessary before using the fetcher.
+
+.. _perforce-fetcher:
+
+Perforce Fetcher (``p4://``)
+----------------------------
+
+This fetcher submodule fetches code from the
+`Perforce <https://www.perforce.com/>`__ source control system. The
+executable used is specified by ``FETCHCMD_p4``, which defaults to "p4".
+The fetcher's temporary working directory is set by
+:term:`P4DIR`, which defaults to "DL_DIR/p4".
+The fetcher does not make use of a perforce client, instead it
+relies on ``p4 files`` to retrieve a list of
+files and ``p4 print`` to transfer the content
+of those files locally.
+
+To use this fetcher, make sure your recipe has proper
+:term:`SRC_URI`, :term:`SRCREV`, and
+:term:`PV` values. The p4 executable is able to use the
+config file defined by your system's ``P4CONFIG`` environment variable
+in order to define the Perforce server URL and port, username, and
+password if you do not wish to keep those values in a recipe itself. If
+you choose not to use ``P4CONFIG``, or to explicitly set variables that
+``P4CONFIG`` can contain, you can specify the ``P4PORT`` value, which is
+the server's URL and port number, and you can specify a username and
+password directly in your recipe within ``SRC_URI``.
+
+Here is an example that relies on ``P4CONFIG`` to specify the server URL
+and port, username, and password, and fetches the Head Revision: ::
+
+   SRC_URI = "p4://example-depot/main/source/..."
+   SRCREV = "${AUTOREV}"
+   PV = "p4-${SRCPV}"
+   S = "${WORKDIR}/p4"
+
+Here is an example that specifies the server URL and port, username, and
+password, and fetches a Revision based on a Label: ::
+
+   P4PORT = "tcp:p4server.example.net:1666"
+   SRC_URI = "p4://user:passwd@example-depot/main/source/..."
+   SRCREV = "release-1.0"
+   PV = "p4-${SRCPV}"
+   S = "${WORKDIR}/p4"
+
+.. note::
+
+   You should always set S to "${WORKDIR}/p4" in your recipe.
+
+By default, the fetcher strips the depot location from the local file paths. In
+the above example, the content of ``example-depot/main/source/`` will be placed
+in ``${WORKDIR}/p4``.  For situations where preserving parts of the remote depot
+paths locally is desirable, the fetcher supports two parameters:
+
+- *"module":*
+    The top-level depot location or directory to fetch. The value of this
+    parameter can also point to a single file within the depot, in which case
+    the local file path will include the module path.
+- *"remotepath":*
+    When used with the value "``keep``", the fetcher will mirror the full depot
+    paths locally for the specified location, even in combination with the
+    ``module`` parameter.
+
+Here is an example use of the the ``module`` parameter: ::
+
+   SRC_URI = "p4://user:passwd@example-depot/main;module=source/..."
+
+In this case, the content of the top-level directory ``source/`` will be fetched
+to ``${P4DIR}``, including the directory itself.  The top-level directory will
+be accesible at ``${P4DIR}/source/``.
+
+Here is an example use of the the ``remotepath`` parameter: ::
+
+   SRC_URI = "p4://user:passwd@example-depot/main;module=source/...;remotepath=keep"
+
+In this case, the content of the top-level directory ``source/`` will be fetched
+to ``${P4DIR}``, but the complete depot paths will be mirrored locally. The
+top-level directory will be accessible at
+``${P4DIR}/example-depot/main/source/``.
+
+.. _repo-fetcher:
+
+Repo Fetcher (``repo://``)
+--------------------------
+
+This fetcher submodule fetches code from ``google-repo`` source control
+system. The fetcher works by initiating and syncing sources of the
+repository into :term:`REPODIR`, which is usually
+``${DL_DIR}/repo``.
+
+This fetcher supports the following parameters:
+
+-  *"protocol":* Protocol to fetch the repository manifest (default:
+   git).
+
+-  *"branch":* Branch or tag of repository to get (default: master).
+
+-  *"manifest":* Name of the manifest file (default: ``default.xml``).
+
+Here are some example URLs: ::
+
+   SRC_URI = "repo://REPOROOT;protocol=git;branch=some_branch;manifest=my_manifest.xml"
+   SRC_URI = "repo://REPOROOT;protocol=file;branch=some_branch;manifest=my_manifest.xml"
+
+.. _az-fetcher:
+
+Az Fetcher (``az://``)
+--------------------------
+
+This submodule fetches data from an
+`Azure Storage account <https://docs.microsoft.com/en-us/azure/storage/>`__ ,
+it inherits its functionality from the HTTP wget fetcher, but modifies its
+behavior to accomodate the usage of a
+`Shared Access Signature (SAS) <https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview>`__
+for non-public data.
+
+Such functionality is set by the variable:
+
+-  :term:`AZ_SAS`: The Azure Storage Shared Access Signature provides secure
+   delegate access to resources, if this variable is set, the Az Fetcher will
+   use it when fetching artifacts from the cloud.
+
+You can specify the AZ_SAS variable as shown below: ::
+
+   AZ_SAS = "se=2021-01-01&sp=r&sv=2018-11-09&sr=c&skoid=<skoid>&sig=<signature>"
+
+Here is an example URL: ::
+
+   SRC_URI = "az://<azure-storage-account>.blob.core.windows.net/<foo_container>/<bar_file>"
+
+It can also be used when setting mirrors definitions using the :term:`PREMIRRORS` variable.
+
+Other Fetchers
+--------------
+
+Fetch submodules also exist for the following:
+
+-  Bazaar (``bzr://``)
+
+-  Mercurial (``hg://``)
+
+-  npm (``npm://``)
+
+-  OSC (``osc://``)
+
+-  Secure FTP (``sftp://``)
+
+-  Secure Shell (``ssh://``)
+
+-  Trees using Git Annex (``gitannex://``)
+
+No documentation currently exists for these lesser used fetcher
+submodules. However, you might find the code helpful and readable.
+
+Auto Revisions
+==============
+
+We need to document ``AUTOREV`` and ``SRCREV_FORMAT`` here.
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
deleted file mode 100644
index d1bfc233..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
+++ /dev/null
@@ -1,868 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<chapter>
-<title>File Download Support</title>
-
-    <para>
-        BitBake's fetch module is a standalone piece of library code
-        that deals with the intricacies of downloading source code
-        and files from remote systems.
-        Fetching source code is one of the cornerstones of building software.
-        As such, this module forms an important part of BitBake.
-    </para>
-
-    <para>
-        The current fetch module is called "fetch2" and refers to the
-        fact that it is the second major version of the API.
-        The original version is obsolete and has been removed from the codebase.
-        Thus, in all cases, "fetch" refers to "fetch2" in this
-        manual.
-    </para>
-
-    <section id='the-download-fetch'>
-        <title>The Download (Fetch)</title>
-
-        <para>
-            BitBake takes several steps when fetching source code or files.
-            The fetcher codebase deals with two distinct processes in order:
-            obtaining the files from somewhere (cached or otherwise)
-            and then unpacking those files into a specific location and
-            perhaps in a specific way.
-            Getting and unpacking the files is often optionally followed
-            by patching.
-            Patching, however, is not covered by this module.
-        </para>
-
-        <para>
-            The code to execute the first part of this process, a fetch,
-            looks something like the following:
-            <literallayout class='monospaced'>
-     src_uri = (d.getVar('SRC_URI') or "").split()
-     fetcher = bb.fetch2.Fetch(src_uri, d)
-     fetcher.download()
-            </literallayout>
-            This code sets up an instance of the fetch class.
-            The instance uses a space-separated list of URLs from the
-            <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
-            variable and then calls the <filename>download</filename>
-            method to download the files.
-        </para>
-
-        <para>
-            The instantiation of the fetch class is usually followed by:
-            <literallayout class='monospaced'>
-     rootdir = l.getVar('WORKDIR')
-     fetcher.unpack(rootdir)
-            </literallayout>
-            This code unpacks the downloaded files to the
-            specified by <filename>WORKDIR</filename>.
-            <note>
-                For convenience, the naming in these examples matches
-                the variables used by OpenEmbedded.
-                If you want to see the above code in action, examine
-                the OpenEmbedded class file <filename>base.bbclass</filename>.
-            </note>
-            The <filename>SRC_URI</filename> and <filename>WORKDIR</filename>
-            variables are not hardcoded into the fetcher, since those fetcher
-            methods can be (and are) called with different variable names.
-            In OpenEmbedded for example, the shared state (sstate) code uses
-            the fetch module to fetch the sstate files.
-        </para>
-
-        <para>
-            When the <filename>download()</filename> method is called,
-            BitBake tries to resolve the URLs by looking for source files
-            in a specific search order:
-            <itemizedlist>
-                <listitem><para><emphasis>Pre-mirror Sites:</emphasis>
-                    BitBake first uses pre-mirrors to try and find source files.
-                    These locations are defined using the
-                    <link linkend='var-bb-PREMIRRORS'><filename>PREMIRRORS</filename></link>
-                    variable.
-                    </para></listitem>
-                <listitem><para><emphasis>Source URI:</emphasis>
-                    If pre-mirrors fail, BitBake uses the original URL (e.g from
-                    <filename>SRC_URI</filename>).
-                    </para></listitem>
-                <listitem><para><emphasis>Mirror Sites:</emphasis>
-                    If fetch failures occur, BitBake next uses mirror locations as
-                    defined by the
-                    <link linkend='var-bb-MIRRORS'><filename>MIRRORS</filename></link>
-                    variable.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            For each URL passed to the fetcher, the fetcher
-            calls the submodule that handles that particular URL type.
-            This behavior can be the source of some confusion when you
-            are providing URLs for the <filename>SRC_URI</filename>
-            variable.
-            Consider the following two URLs:
-            <literallayout class='monospaced'>
-     http://git.yoctoproject.org/git/poky;protocol=git
-     git://git.yoctoproject.org/git/poky;protocol=http
-            </literallayout>
-            In the former case, the URL is passed to the
-            <filename>wget</filename> fetcher, which does not
-            understand "git".
-            Therefore, the latter case is the correct form since the
-            Git fetcher does know how to use HTTP as a transport.
-        </para>
-
-        <para>
-            Here are some examples that show commonly used mirror
-            definitions:
-            <literallayout class='monospaced'>
-     PREMIRRORS ?= "\
-         bzr://.*/.*   http://somemirror.org/sources/ \n \
-         cvs://.*/.*   http://somemirror.org/sources/ \n \
-         git://.*/.*   http://somemirror.org/sources/ \n \
-         hg://.*/.*    http://somemirror.org/sources/ \n \
-         osc://.*/.*   http://somemirror.org/sources/ \n \
-         p4://.*/.*    http://somemirror.org/sources/ \n \
-         svn://.*/.*   http://somemirror.org/sources/ \n"
-
-     MIRRORS =+ "\
-         ftp://.*/.*      http://somemirror.org/sources/ \n \
-         http://.*/.*     http://somemirror.org/sources/ \n \
-         https://.*/.*    http://somemirror.org/sources/ \n"
-            </literallayout>
-            It is useful to note that BitBake supports
-            cross-URLs.
-            It is possible to mirror a Git repository on an HTTP
-            server as a tarball.
-            This is what the <filename>git://</filename> mapping in
-            the previous example does.
-        </para>
-
-        <para>
-            Since network accesses are slow, BitBake maintains a
-            cache of files downloaded from the network.
-            Any source files that are not local (i.e.
-            downloaded from the Internet) are placed into the download
-            directory, which is specified by the
-            <link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
-            variable.
-        </para>
-
-        <para>
-            File integrity is of key importance for reproducing builds.
-            For non-local archive downloads, the fetcher code can verify
-            SHA-256 and MD5 checksums to ensure the archives have been
-            downloaded correctly.
-            You can specify these checksums by using the
-            <filename>SRC_URI</filename> variable with the appropriate
-            varflags as follows:
-            <literallayout class='monospaced'>
-     SRC_URI[md5sum] = "<replaceable>value</replaceable>"
-     SRC_URI[sha256sum] = "<replaceable>value</replaceable>"
-            </literallayout>
-            You can also specify the checksums as parameters on the
-            <filename>SRC_URI</filename> as shown below:
-            <literallayout class='monospaced'>
-     SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"
-            </literallayout>
-            If multiple URIs exist, you can specify the checksums either
-            directly as in the previous example, or you can name the URLs.
-            The following syntax shows how you name the URIs:
-            <literallayout class='monospaced'>
-     SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
-     SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d
-            </literallayout>
-            After a file has been downloaded and has had its checksum checked,
-            a ".done" stamp is placed in <filename>DL_DIR</filename>.
-            BitBake uses this stamp during subsequent builds to avoid
-            downloading or comparing a checksum for the file again.
-            <note>
-                It is assumed that local storage is safe from data corruption.
-                If this were not the case, there would be bigger issues to worry about.
-            </note>
-        </para>
-
-        <para>
-            If
-            <link linkend='var-bb-BB_STRICT_CHECKSUM'><filename>BB_STRICT_CHECKSUM</filename></link>
-            is set, any download without a checksum triggers an
-            error message.
-            The
-            <link linkend='var-bb-BB_NO_NETWORK'><filename>BB_NO_NETWORK</filename></link>
-            variable can be used to make any attempted network access a fatal
-            error, which is useful for checking that mirrors are complete
-            as well as other things.
-        </para>
-    </section>
-
-    <section id='bb-the-unpack'>
-        <title>The Unpack</title>
-
-        <para>
-            The unpack process usually immediately follows the download.
-            For all URLs except Git URLs, BitBake uses the common
-            <filename>unpack</filename> method.
-        </para>
-
-        <para>
-            A number of parameters exist that you can specify within the
-            URL to govern the behavior of the unpack stage:
-            <itemizedlist>
-                <listitem><para><emphasis>unpack:</emphasis>
-                    Controls whether the URL components are unpacked.
-                    If set to "1", which is the default, the components
-                    are unpacked.
-                    If set to "0", the unpack stage leaves the file alone.
-                    This parameter is useful when you want an archive to be
-                    copied in and not be unpacked.
-                    </para></listitem>
-                <listitem><para><emphasis>dos:</emphasis>
-                    Applies to <filename>.zip</filename> and
-                    <filename>.jar</filename> files and specifies whether to
-                    use DOS line ending conversion on text files.
-                    </para></listitem>
-                <listitem><para><emphasis>basepath:</emphasis>
-                    Instructs the unpack stage to strip the specified
-                    directories from the source path when unpacking.
-                    </para></listitem>
-                <listitem><para><emphasis>subdir:</emphasis>
-                    Unpacks the specific URL to the specified subdirectory
-                    within the root directory.
-                    </para></listitem>
-            </itemizedlist>
-            The unpack call automatically decompresses and extracts files
-            with ".Z", ".z", ".gz", ".xz", ".zip", ".jar", ".ipk", ".rpm".
-            ".srpm", ".deb" and ".bz2" extensions as well as various combinations
-            of tarball extensions.
-        </para>
-
-        <para>
-            As mentioned, the Git fetcher has its own unpack method that
-            is optimized to work with Git trees.
-            Basically, this method works by cloning the tree into the final
-            directory.
-            The process is completed using references so that there is
-            only one central copy of the Git metadata needed.
-        </para>
-    </section>
-
-    <section id='bb-fetchers'>
-        <title>Fetchers</title>
-
-        <para>
-            As mentioned earlier, the URL prefix determines which
-            fetcher submodule BitBake uses.
-            Each submodule can support different URL parameters,
-            which are described in the following sections.
-        </para>
-
-        <section id='local-file-fetcher'>
-            <title>Local file fetcher (<filename>file://</filename>)</title>
-
-            <para>
-                This submodule handles URLs that begin with
-                <filename>file://</filename>.
-                The filename you specify within the URL can be
-                either an absolute or relative path to a file.
-                If the filename is relative, the contents of the
-                <link linkend='var-bb-FILESPATH'><filename>FILESPATH</filename></link>
-                variable is used in the same way
-                <filename>PATH</filename> is used to find executables.
-                If the file cannot be found, it is assumed that it is available in
-                <link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
-                by the time the <filename>download()</filename> method is called.
-            </para>
-
-            <para>
-                If you specify a directory, the entire directory is
-                unpacked.
-            </para>
-
-            <para>
-                Here are a couple of example URLs, the first relative and
-                the second absolute:
-                <literallayout class='monospaced'>
-     SRC_URI = "file://relativefile.patch"
-     SRC_URI = "file:///Users/ich/very_important_software"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='http-ftp-fetcher'>
-            <title>HTTP/FTP wget fetcher (<filename>http://</filename>, <filename>ftp://</filename>, <filename>https://</filename>)</title>
-
-            <para>
-                This fetcher obtains files from web and FTP servers.
-                Internally, the fetcher uses the wget utility.
-            </para>
-
-            <para>
-                The executable and parameters used are specified by the
-                <filename>FETCHCMD_wget</filename> variable, which defaults
-                to sensible values.
-                The fetcher supports a parameter "downloadfilename" that
-                allows the name of the downloaded file to be specified.
-                Specifying the name of the downloaded file is useful
-                for avoiding collisions in
-                <link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
-                when dealing with multiple files that have the same name.
-            </para>
-
-            <para>
-                Some example URLs are as follows:
-                <literallayout class='monospaced'>
-     SRC_URI = "http://oe.handhelds.org/not_there.aac"
-     SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
-     SRC_URI = "ftp://you@oe.handhelds.org/home/you/secret.plan"
-                </literallayout>
-            </para>
-            <note>
-               Because URL parameters are delimited by semi-colons, this can
-               introduce ambiguity when parsing URLs that also contain semi-colons,
-               for example:
-                <literallayout class='monospaced'>
-     SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git;a=snapshot;h=a5dd47"
-                </literallayout>
-               Such URLs should should be modified by replacing semi-colons with '&amp;' characters:
-               <literallayout class='monospaced'>
-     SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&amp;a=snapshot&amp;h=a5dd47"
-                </literallayout>
-                In most cases this should work. Treating semi-colons and '&amp;' in queries
-                identically is recommended by the World Wide Web Consortium (W3C).
-                Note that due to the nature of the URL, you may have to specify the name
-                of the downloaded file as well:
-              <literallayout class='monospaced'>
-     SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&amp;a=snapshot&amp;h=a5dd47;downloadfilename=myfile.bz2"
-                </literallayout>
-            </note>
-        </section>
-
-        <section id='cvs-fetcher'>
-            <title>CVS fetcher (<filename>(cvs://</filename>)</title>
-
-            <para>
-                This submodule handles checking out files from the
-                CVS version control system.
-                You can configure it using a number of different variables:
-                <itemizedlist>
-                    <listitem><para><emphasis><filename>FETCHCMD_cvs</filename>:</emphasis>
-                        The name of the executable to use when running
-                        the <filename>cvs</filename> command.
-                        This name is usually "cvs".
-                        </para></listitem>
-                    <listitem><para><emphasis><filename>SRCDATE</filename>:</emphasis>
-                        The date to use when fetching the CVS source code.
-                        A special value of "now" causes the checkout to
-                        be updated on every build.
-                        </para></listitem>
-                    <listitem><para><emphasis><link linkend='var-bb-CVSDIR'><filename>CVSDIR</filename></link>:</emphasis>
-                        Specifies where a temporary checkout is saved.
-                        The location is often <filename>DL_DIR/cvs</filename>.
-                        </para></listitem>
-                    <listitem><para><emphasis><filename>CVS_PROXY_HOST</filename>:</emphasis>
-                        The name to use as a "proxy=" parameter to the
-                        <filename>cvs</filename> command.
-                        </para></listitem>
-                    <listitem><para><emphasis><filename>CVS_PROXY_PORT</filename>:</emphasis>
-                        The port number to use as a "proxyport=" parameter to
-                        the <filename>cvs</filename> command.
-                        </para></listitem>
-                </itemizedlist>
-                As well as the standard username and password URL syntax,
-                you can also configure the fetcher with various URL parameters:
-            </para>
-
-            <para>
-                The supported parameters are as follows:
-                <itemizedlist>
-                    <listitem><para><emphasis>"method":</emphasis>
-                        The protocol over which to communicate with the CVS
-                        server.
-                        By default, this protocol is "pserver".
-                        If "method" is set to "ext", BitBake examines the
-                        "rsh" parameter and sets <filename>CVS_RSH</filename>.
-                        You can use "dir" for local directories.
-                        </para></listitem>
-                    <listitem><para><emphasis>"module":</emphasis>
-                        Specifies the module to check out.
-                        You must supply this parameter.
-                        </para></listitem>
-                    <listitem><para><emphasis>"tag":</emphasis>
-                        Describes which CVS TAG should be used for
-                        the checkout.
-                        By default, the TAG is empty.
-                        </para></listitem>
-                    <listitem><para><emphasis>"date":</emphasis>
-                        Specifies a date.
-                        If no "date" is specified, the
-                        <link linkend='var-bb-SRCDATE'><filename>SRCDATE</filename></link>
-                        of the configuration is used to checkout a specific date.
-                        The special value of "now" causes the checkout to be
-                        updated on every build.
-                        </para></listitem>
-                    <listitem><para><emphasis>"localdir":</emphasis>
-                        Used to rename the module.
-                        Effectively, you are renaming the output directory
-                        to which the module is unpacked.
-                        You are forcing the module into a special
-                        directory relative to
-                        <link linkend='var-bb-CVSDIR'><filename>CVSDIR</filename></link>.
-                        </para></listitem>
-                    <listitem><para><emphasis>"rsh"</emphasis>
-                        Used in conjunction with the "method" parameter.
-                        </para></listitem>
-                    <listitem><para><emphasis>"scmdata":</emphasis>
-                        Causes the CVS metadata to be maintained in the tarball
-                        the fetcher creates when set to "keep".
-                        The tarball is expanded into the work directory.
-                        By default, the CVS metadata is removed.
-                        </para></listitem>
-                    <listitem><para><emphasis>"fullpath":</emphasis>
-                        Controls whether the resulting checkout is at the
-                        module level, which is the default, or is at deeper
-                        paths.
-                        </para></listitem>
-                    <listitem><para><emphasis>"norecurse":</emphasis>
-                        Causes the fetcher to only checkout the specified
-                        directory with no recurse into any subdirectories.
-                        </para></listitem>
-                    <listitem><para><emphasis>"port":</emphasis>
-                        The port to which the CVS server connects.
-                        </para></listitem>
-                </itemizedlist>
-                Some example URLs are as follows:
-                <literallayout class='monospaced'>
-     SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
-     SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='svn-fetcher'>
-            <title>Subversion (SVN) Fetcher (<filename>svn://</filename>)</title>
-
-            <para>
-                This fetcher submodule fetches code from the
-                Subversion source control system.
-                The executable used is specified by
-                <filename>FETCHCMD_svn</filename>, which defaults
-                to "svn".
-                The fetcher's temporary working directory is set by
-                <link linkend='var-bb-SVNDIR'><filename>SVNDIR</filename></link>,
-                which is usually <filename>DL_DIR/svn</filename>.
-            </para>
-
-            <para>
-                The supported parameters are as follows:
-                <itemizedlist>
-                    <listitem><para><emphasis>"module":</emphasis>
-                        The name of the svn module to checkout.
-                        You must provide this parameter.
-                        You can think of this parameter as the top-level
-                        directory of the repository data you want.
-                        </para></listitem>
-                    <listitem><para><emphasis>"path_spec":</emphasis>
-                        A specific directory in which to checkout the
-                        specified svn module.
-                        </para></listitem>
-                    <listitem><para><emphasis>"protocol":</emphasis>
-                        The protocol to use, which defaults to "svn".
-                        If "protocol" is set to "svn+ssh", the "ssh"
-                        parameter is also used.
-                        </para></listitem>
-                    <listitem><para><emphasis>"rev":</emphasis>
-                        The revision of the source code to checkout.
-                        </para></listitem>
-                    <listitem><para><emphasis>"scmdata":</emphasis>
-                        Causes the “.svn” directories to be available during
-                        compile-time when set to "keep".
-                        By default, these directories are removed.
-                        </para></listitem>
-                    <listitem><para><emphasis>"ssh":</emphasis>
-                        An optional parameter used when "protocol" is set
-                        to "svn+ssh".
-                        You can use this parameter to specify the ssh
-                        program used by svn.
-                        </para></listitem>
-                    <listitem><para><emphasis>"transportuser":</emphasis>
-                        When required, sets the username for the transport.
-                        By default, this parameter is empty.
-                        The transport username is different than the username
-                        used in the main URL, which is passed to the subversion
-                        command.
-                        </para></listitem>
-                </itemizedlist>
-                Following are three examples using svn:
-                <literallayout class='monospaced'>
-     SRC_URI = "svn://myrepos/proj1;module=vip;protocol=http;rev=667"
-     SRC_URI = "svn://myrepos/proj1;module=opie;protocol=svn+ssh"
-     SRC_URI = "svn://myrepos/proj1;module=trunk;protocol=http;path_spec=${MY_DIR}/proj1"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='git-fetcher'>
-            <title>Git Fetcher (<filename>git://</filename>)</title>
-
-            <para>
-                This fetcher submodule fetches code from the Git
-                source control system.
-                The fetcher works by creating a bare clone of the
-                remote into
-                <link linkend='var-bb-GITDIR'><filename>GITDIR</filename></link>,
-                which is usually <filename>DL_DIR/git2</filename>.
-                This bare clone is then cloned into the work directory during the
-                unpack stage when a specific tree is checked out.
-                This is done using alternates and by reference to
-                minimize the amount of duplicate data on the disk and
-                make the unpack process fast.
-                The executable used can be set with
-                <filename>FETCHCMD_git</filename>.
-            </para>
-
-            <para>
-                This fetcher supports the following parameters:
-                <itemizedlist>
-                    <listitem><para><emphasis>"protocol":</emphasis>
-                        The protocol used to fetch the files.
-                        The default is "git" when a hostname is set.
-                        If a hostname is not set, the Git protocol is "file".
-                        You can also use "http", "https", "ssh" and "rsync".
-                        </para></listitem>
-                    <listitem><para><emphasis>"nocheckout":</emphasis>
-                        Tells the fetcher to not checkout source code when
-                        unpacking when set to "1".
-                        Set this option for the URL where there is a custom
-                        routine to checkout code.
-                        The default is "0".
-                        </para></listitem>
-                    <listitem><para><emphasis>"rebaseable":</emphasis>
-                        Indicates that the upstream Git repository can be rebased.
-                        You should set this parameter to "1" if
-                        revisions can become detached from branches.
-                        In this case, the source mirror tarball is done per
-                        revision, which has a loss of efficiency.
-                        Rebasing the upstream Git repository could cause the
-                        current revision to disappear from the upstream repository.
-                        This option reminds the fetcher to preserve the local cache
-                        carefully for future use.
-                        The default value for this parameter is "0".
-                        </para></listitem>
-                    <listitem><para><emphasis>"nobranch":</emphasis>
-                        Tells the fetcher to not check the SHA validation
-                        for the branch when set to "1".
-                        The default is "0".
-                        Set this option for the recipe that refers to
-                        the commit that is valid for a tag instead of
-                        the branch.
-                        </para></listitem>
-                    <listitem><para><emphasis>"bareclone":</emphasis>
-                        Tells the fetcher to clone a bare clone into the
-                        destination directory without checking out a working tree.
-                        Only the raw Git metadata is provided.
-                        This parameter implies the "nocheckout" parameter as well.
-                        </para></listitem>
-                    <listitem><para><emphasis>"branch":</emphasis>
-                        The branch(es) of the Git tree to clone.
-                        If unset, this is assumed to be "master".
-                        The number of branch parameters much match the number of
-                        name parameters.
-                        </para></listitem>
-                    <listitem><para><emphasis>"rev":</emphasis>
-                        The revision to use for the checkout.
-                        The default is "master".
-                        </para></listitem>
-                    <listitem><para><emphasis>"tag":</emphasis>
-                        Specifies a tag to use for the checkout.
-                        To correctly resolve tags, BitBake must access the
-                        network.
-                        For that reason, tags are often not used.
-                        As far as Git is concerned, the "tag" parameter behaves
-                        effectively the same as the "rev" parameter.
-                        </para></listitem>
-                    <listitem><para><emphasis>"subpath":</emphasis>
-                        Limits the checkout to a specific subpath of the tree.
-                        By default, the whole tree is checked out.
-                        </para></listitem>
-                    <listitem><para><emphasis>"destsuffix":</emphasis>
-                        The name of the path in which to place the checkout.
-                        By default, the path is <filename>git/</filename>.
-                        </para></listitem>
-                    <listitem><para><emphasis>"usehead":</emphasis>
-                        Enables local <filename>git://</filename> URLs to use the
-                        current branch HEAD as the revision for use with
-                        <filename>AUTOREV</filename>.
-                        The "usehead" parameter implies no branch and only works
-                        when the transfer protocol is
-                        <filename>file://</filename>.
-                        </para></listitem>
-                </itemizedlist>
-                Here are some example URLs:
-                <literallayout class='monospaced'>
-     SRC_URI = "git://git.oe.handhelds.org/git/vip.git;tag=version-1"
-     SRC_URI = "git://git.oe.handhelds.org/git/vip.git;protocol=http"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='gitsm-fetcher'>
-            <title>Git Submodule Fetcher (<filename>gitsm://</filename>)</title>
-
-            <para>
-                This fetcher submodule inherits from the
-                <link linkend='git-fetcher'>Git fetcher</link> and extends
-                that fetcher's behavior by fetching a repository's submodules.
-                <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
-                is passed to the Git fetcher as described in the
-                "<link linkend='git-fetcher'>Git Fetcher (<filename>git://</filename>)</link>"
-                section.
-                <note>
-                    <title>Notes and Warnings</title>
-                    <para>
-                        You must clean a recipe when switching between
-                        '<filename>git://</filename>' and
-                        '<filename>gitsm://</filename>' URLs.
-                    </para>
-
-                    <para>
-                        The Git Submodules fetcher is not a complete fetcher
-                        implementation.
-                        The fetcher has known issues where it does not use the
-                        normal source mirroring infrastructure properly. Further,
-                        the submodule sources it fetches are not visible to the
-                        licensing and source archiving infrastructures.
-                    </para>
-                </note>
-            </para>
-        </section>
-
-        <section id='clearcase-fetcher'>
-            <title>ClearCase Fetcher (<filename>ccrc://</filename>)</title>
-
-            <para>
-                This fetcher submodule fetches code from a
-                <ulink url='http://en.wikipedia.org/wiki/Rational_ClearCase'>ClearCase</ulink>
-                repository.
-            </para>
-
-            <para>
-                To use this fetcher, make sure your recipe has proper
-                <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>,
-                <link linkend='var-bb-SRCREV'><filename>SRCREV</filename></link>, and
-                <link linkend='var-bb-PV'><filename>PV</filename></link> settings.
-                Here is an example:
-                <literallayout class='monospaced'>
-     SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
-     SRCREV = "EXAMPLE_CLEARCASE_TAG"
-     PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
-                </literallayout>
-                The fetcher uses the <filename>rcleartool</filename> or
-                <filename>cleartool</filename> remote client, depending on
-                which one is available.
-            </para>
-
-            <para>
-                Following are options for the <filename>SRC_URI</filename>
-                statement:
-                <itemizedlist>
-                    <listitem><para><emphasis><filename>vob</filename></emphasis>:
-                        The name, which must include the
-                        prepending "/" character, of the ClearCase VOB.
-                        This option is required.
-                        </para></listitem>
-                    <listitem><para><emphasis><filename>module</filename></emphasis>:
-                        The module, which must include the
-                        prepending "/" character, in the selected VOB.
-                        <note>
-                            The <filename>module</filename> and <filename>vob</filename>
-                            options are combined to create the <filename>load</filename> rule in
-                            the view config spec.
-                            As an example, consider the <filename>vob</filename> and
-                            <filename>module</filename> values from the
-                            <filename>SRC_URI</filename> statement at the start of this section.
-                            Combining those values results in the following:
-                            <literallayout class='monospaced'>
-     load /example_vob/example_module
-                            </literallayout>
-                        </note>
-                        </para></listitem>
-                    <listitem><para><emphasis><filename>proto</filename></emphasis>:
-                        The protocol, which can be either <filename>http</filename> or
-                        <filename>https</filename>.
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-
-            <para>
-                By default, the fetcher creates a configuration specification.
-                If you want this specification written to an area other than the default,
-                use the <filename>CCASE_CUSTOM_CONFIG_SPEC</filename> variable
-                in your recipe to define where the specification is written.
-                <note>
-                    the <filename>SRCREV</filename> loses its functionality if you
-                    specify this variable.
-                    However, <filename>SRCREV</filename> is still used to label the
-                    archive after a fetch even though it does not define what is
-                    fetched.
-                </note>
-            </para>
-
-            <para>
-                Here are a couple of other behaviors worth mentioning:
-                <itemizedlist>
-                    <listitem><para>
-                        When using <filename>cleartool</filename>, the login of
-                        <filename>cleartool</filename> is handled by the system.
-                        The login require no special steps.
-                        </para></listitem>
-                    <listitem><para>
-                        In order to use <filename>rcleartool</filename> with authenticated
-                        users, an "rcleartool login" is necessary before using the fetcher.
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-        </section>
-
-        <section id='perforce-fetcher'>
-            <title>Perforce Fetcher (<filename>p4://</filename>)</title>
-
-            <para>
-                This fetcher submodule fetches code from the
-                <ulink url='https://www.perforce.com/'>Perforce</ulink>
-                source control system.
-                The executable used is specified by
-                <filename>FETCHCMD_p4</filename>, which defaults
-                to "p4".
-                The fetcher's temporary working directory is set by
-                <link linkend='var-bb-P4DIR'><filename>P4DIR</filename></link>,
-                which defaults to "DL_DIR/p4".
-            </para>
-
-            <para>
-                To use this fetcher, make sure your recipe has proper
-                <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>,
-                <link linkend='var-bb-SRCREV'><filename>SRCREV</filename></link>, and
-                <link linkend='var-bb-PV'><filename>PV</filename></link> values.
-                The p4 executable is able to use the config file defined by your
-                system's <filename>P4CONFIG</filename> environment variable in
-                order to define the Perforce server URL and port, username, and
-                password if you do not wish to keep those values in a recipe
-                itself.
-                If you choose not to use <filename>P4CONFIG</filename>,
-                or to explicitly set variables that <filename>P4CONFIG</filename>
-                can contain, you can specify the <filename>P4PORT</filename> value,
-                which is the server's URL and port number, and you can
-                specify a username and password directly in your recipe within
-                <filename>SRC_URI</filename>.
-            </para>
-
-            <para>
-                Here is an example that relies on <filename>P4CONFIG</filename>
-                to specify the server URL and port, username, and password, and
-                fetches the Head Revision:
-                <literallayout class='monospaced'>
-    SRC_URI = "p4://example-depot/main/source/..."
-    SRCREV = "${AUTOREV}"
-    PV = "p4-${SRCPV}"
-    S = "${WORKDIR}/p4"
-                </literallayout>
-            </para>
-
-            <para>
-                Here is an example that specifies the server URL and port,
-                username, and password, and fetches a Revision based on a Label:
-                <literallayout class='monospaced'>
-    P4PORT = "tcp:p4server.example.net:1666"
-    SRC_URI = "p4://user:passwd@example-depot/main/source/..."
-    SRCREV = "release-1.0"
-    PV = "p4-${SRCPV}"
-    S = "${WORKDIR}/p4"
-                </literallayout>
-                <note>
-                    You should always set <filename>S</filename>
-                    to <filename>"${WORKDIR}/p4"</filename> in your recipe.
-                </note>
-            </para>
-        </section>
-
-        <section id='repo-fetcher'>
-            <title>Repo Fetcher (<filename>repo://</filename>)</title>
-
-            <para>
-                This fetcher submodule fetches code from
-                <filename>google-repo</filename> source control system.
-                The fetcher works by initiating and syncing sources of the
-                repository into
-                <link linkend='var-bb-REPODIR'><filename>REPODIR</filename></link>,
-                which is usually
-                <link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link><filename>/repo</filename>.
-            </para>
-
-            <para>
-                This fetcher supports the following parameters:
-                <itemizedlist>
-                    <listitem><para>
-                        <emphasis>"protocol":</emphasis>
-                        Protocol to fetch the repository manifest (default: git).
-                        </para></listitem>
-                    <listitem><para>
-                        <emphasis>"branch":</emphasis>
-                        Branch or tag of repository to get (default: master).
-                        </para></listitem>
-                    <listitem><para>
-                        <emphasis>"manifest":</emphasis>
-                        Name of the manifest file (default: <filename>default.xml</filename>).
-                        </para></listitem>
-                </itemizedlist>
-                Here are some example URLs:
-                <literallayout class='monospaced'>
-    SRC_URI = "repo://REPOROOT;protocol=git;branch=some_branch;manifest=my_manifest.xml"
-    SRC_URI = "repo://REPOROOT;protocol=file;branch=some_branch;manifest=my_manifest.xml"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='other-fetchers'>
-            <title>Other Fetchers</title>
-
-            <para>
-                Fetch submodules also exist for the following:
-                <itemizedlist>
-                    <listitem><para>
-                        Bazaar (<filename>bzr://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        Mercurial (<filename>hg://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        npm (<filename>npm://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        OSC (<filename>osc://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        Secure FTP (<filename>sftp://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        Secure Shell (<filename>ssh://</filename>)
-                        </para></listitem>
-                    <listitem><para>
-                        Trees using Git Annex (<filename>gitannex://</filename>)
-                        </para></listitem>
-                </itemizedlist>
-                No documentation currently exists for these lesser used
-                fetcher submodules.
-                However, you might find the code helpful and readable.
-            </para>
-        </section>
-    </section>
-
-    <section id='auto-revisions'>
-        <title>Auto Revisions</title>
-
-        <para>
-            We need to document <filename>AUTOREV</filename> and
-            <filename>SRCREV_FORMAT</filename> here.
-        </para>
-    </section>
-</chapter>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.rst
new file mode 100644
index 00000000..e3fd3215
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.rst
@@ -0,0 +1,415 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+===================
+Hello World Example
+===================
+
+BitBake Hello World
+===================
+
+The simplest example commonly used to demonstrate any new programming
+language or tool is the "`Hello
+World <http://en.wikipedia.org/wiki/Hello_world_program>`__" example.
+This appendix demonstrates, in tutorial form, Hello World within the
+context of BitBake. The tutorial describes how to create a new project
+and the applicable metadata files necessary to allow BitBake to build
+it.
+
+Obtaining BitBake
+=================
+
+See the :ref:`bitbake-user-manual/bitbake-user-manual-hello:obtaining bitbake` section for
+information on how to obtain BitBake. Once you have the source code on
+your machine, the BitBake directory appears as follows: ::
+
+   $ ls -al
+   total 100
+   drwxrwxr-x. 9 wmat wmat  4096 Jan 31 13:44 .
+   drwxrwxr-x. 3 wmat wmat  4096 Feb  4 10:45 ..
+   -rw-rw-r--. 1 wmat wmat   365 Nov 26 04:55 AUTHORS
+   drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 bin
+   drwxrwxr-x. 4 wmat wmat  4096 Jan 31 13:44 build
+   -rw-rw-r--. 1 wmat wmat 16501 Nov 26 04:55 ChangeLog
+   drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 classes
+   drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 conf
+   drwxrwxr-x. 3 wmat wmat  4096 Nov 26 04:55 contrib
+   -rw-rw-r--. 1 wmat wmat 17987 Nov 26 04:55 COPYING
+   drwxrwxr-x. 3 wmat wmat  4096 Nov 26 04:55 doc
+   -rw-rw-r--. 1 wmat wmat    69 Nov 26 04:55 .gitignore
+   -rw-rw-r--. 1 wmat wmat   849 Nov 26 04:55 HEADER
+   drwxrwxr-x. 5 wmat wmat  4096 Jan 31 13:44 lib
+   -rw-rw-r--. 1 wmat wmat   195 Nov 26 04:55 MANIFEST.in
+   -rw-rw-r--. 1 wmat wmat  2887 Nov 26 04:55 TODO
+
+At this point, you should have BitBake cloned to a directory that
+matches the previous listing except for dates and user names.
+
+Setting Up the BitBake Environment
+==================================
+
+First, you need to be sure that you can run BitBake. Set your working
+directory to where your local BitBake files are and run the following
+command: ::
+
+  $ ./bin/bitbake --version
+  BitBake Build Tool Core version 1.23.0, bitbake version 1.23.0
+
+The console output tells you what version
+you are running.
+
+The recommended method to run BitBake is from a directory of your
+choice. To be able to run BitBake from any directory, you need to add
+the executable binary to your binary to your shell's environment
+``PATH`` variable. First, look at your current ``PATH`` variable by
+entering the following: ::
+
+  $ echo $PATH
+
+Next, add the directory location
+for the BitBake binary to the ``PATH``. Here is an example that adds the
+``/home/scott-lenovo/bitbake/bin`` directory to the front of the
+``PATH`` variable: ::
+
+  $ export PATH=/home/scott-lenovo/bitbake/bin:$PATH
+
+You should now be able to enter the ``bitbake`` command from the command
+line while working from any directory.
+
+The Hello World Example
+=======================
+
+The overall goal of this exercise is to build a complete "Hello World"
+example utilizing task and layer concepts. Because this is how modern
+projects such as OpenEmbedded and the Yocto Project utilize BitBake, the
+example provides an excellent starting point for understanding BitBake.
+
+To help you understand how to use BitBake to build targets, the example
+starts with nothing but the ``bitbake`` command, which causes BitBake to
+fail and report problems. The example progresses by adding pieces to the
+build to eventually conclude with a working, minimal "Hello World"
+example.
+
+While every attempt is made to explain what is happening during the
+example, the descriptions cannot cover everything. You can find further
+information throughout this manual. Also, you can actively participate
+in the :oe_lists:`/g/bitbake-devel`
+discussion mailing list about the BitBake build tool.
+
+.. note::
+
+   This example was inspired by and drew heavily from
+   `Mailing List post - The BitBake equivalent of "Hello, World!"
+   <http://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html>`_.
+
+As stated earlier, the goal of this example is to eventually compile
+"Hello World". However, it is unknown what BitBake needs and what you
+have to provide in order to achieve that goal. Recall that BitBake
+utilizes three types of metadata files:
+:ref:`bitbake-user-manual/bitbake-user-manual-intro:configuration files`,
+:ref:`bitbake-user-manual/bitbake-user-manual-intro:classes`, and
+:ref:`bitbake-user-manual/bitbake-user-manual-intro:recipes`.
+But where do they go? How does BitBake find
+them? BitBake's error messaging helps you answer these types of
+questions and helps you better understand exactly what is going on.
+
+Following is the complete "Hello World" example.
+
+#.  **Create a Project Directory:** First, set up a directory for the
+    "Hello World" project. Here is how you can do so in your home
+    directory: ::
+
+      $ mkdir ~/hello
+      $ cd ~/hello
+
+    This is the directory that
+    BitBake will use to do all of its work. You can use this directory
+    to keep all the metafiles needed by BitBake. Having a project
+    directory is a good way to isolate your project.
+
+#.  **Run BitBake:** At this point, you have nothing but a project
+    directory. Run the ``bitbake`` command and see what it does: ::
+
+       $ bitbake
+       The BBPATH variable is not set and bitbake did not
+       find a conf/bblayers.conf file in the expected location.
+       Maybe you accidentally invoked bitbake from the wrong directory?
+       DEBUG: Removed the following variables from the environment:
+       GNOME_DESKTOP_SESSION_ID, XDG_CURRENT_DESKTOP,
+       GNOME_KEYRING_CONTROL, DISPLAY, SSH_AGENT_PID, LANG, no_proxy,
+       XDG_SESSION_PATH, XAUTHORITY, SESSION_MANAGER, SHLVL,
+       MANDATORY_PATH, COMPIZ_CONFIG_PROFILE, WINDOWID, EDITOR,
+       GPG_AGENT_INFO, SSH_AUTH_SOCK, GDMSESSION, GNOME_KEYRING_PID,
+       XDG_SEAT_PATH, XDG_CONFIG_DIRS, LESSOPEN, DBUS_SESSION_BUS_ADDRESS,
+       _, XDG_SESSION_COOKIE, DESKTOP_SESSION, LESSCLOSE, DEFAULTS_PATH,
+       UBUNTU_MENUPROXY, OLDPWD, XDG_DATA_DIRS, COLORTERM, LS_COLORS
+
+    The majority of this output is specific to environment variables that
+    are not directly relevant to BitBake. However, the very first
+    message regarding the ``BBPATH`` variable and the
+    ``conf/bblayers.conf`` file is relevant.
+
+    When you run BitBake, it begins looking for metadata files. The
+    :term:`BBPATH` variable is what tells BitBake where
+    to look for those files. ``BBPATH`` is not set and you need to set
+    it. Without ``BBPATH``, BitBake cannot find any configuration files
+    (``.conf``) or recipe files (``.bb``) at all. BitBake also cannot
+    find the ``bitbake.conf`` file.
+
+#.  **Setting BBPATH:** For this example, you can set ``BBPATH`` in
+    the same manner that you set ``PATH`` earlier in the appendix. You
+    should realize, though, that it is much more flexible to set the
+    ``BBPATH`` variable up in a configuration file for each project.
+
+    From your shell, enter the following commands to set and export the
+    ``BBPATH`` variable: ::
+
+      $ BBPATH="projectdirectory"
+      $ export BBPATH
+
+    Use your actual project directory in the command. BitBake uses that
+    directory to find the metadata it needs for your project.
+
+    .. note::
+
+       When specifying your project directory, do not use the tilde
+       ("~") character as BitBake does not expand that character as the
+       shell would.
+
+#.  **Run BitBake:** Now that you have ``BBPATH`` defined, run the
+    ``bitbake`` command again: ::
+
+       $ bitbake
+       ERROR: Traceback (most recent call last):
+         File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
+           return func(fn, *args)
+         File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 173, in parse_config_file
+           return bb.parse.handle(fn, data, include)
+         File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 99, in handle
+           return h['handle'](fn, data, include)
+         File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 120, in handle
+           abs_fn = resolve_file(fn, data)
+         File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 117, in resolve_file
+           raise IOError("file %s not found in %s" % (fn, bbpath))
+       IOError: file conf/bitbake.conf not found in /home/scott-lenovo/hello
+
+       ERROR: Unable to parse conf/bitbake.conf: file conf/bitbake.conf not found in /home/scott-lenovo/hello
+
+    This sample output shows that BitBake could not find the
+    ``conf/bitbake.conf`` file in the project directory. This file is
+    the first thing BitBake must find in order to build a target. And,
+    since the project directory for this example is empty, you need to
+    provide a ``conf/bitbake.conf`` file.
+
+#.  **Creating conf/bitbake.conf:** The ``conf/bitbake.conf`` includes
+    a number of configuration variables BitBake uses for metadata and
+    recipe files. For this example, you need to create the file in your
+    project directory and define some key BitBake variables. For more
+    information on the ``bitbake.conf`` file, see
+    http://git.openembedded.org/bitbake/tree/conf/bitbake.conf.
+
+    Use the following commands to create the ``conf`` directory in the
+    project directory: ::
+
+      $ mkdir conf
+
+    From within the ``conf`` directory,
+    use some editor to create the ``bitbake.conf`` so that it contains
+    the following: ::
+
+       PN  = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
+
+       TMPDIR  = "${TOPDIR}/tmp"
+       CACHE   = "${TMPDIR}/cache"
+       STAMP   = "${TMPDIR}/${PN}/stamps"
+       T       = "${TMPDIR}/${PN}/work"
+       B       = "${TMPDIR}/${PN}"
+
+    .. note::
+
+       Without a value for PN , the variables STAMP , T , and B , prevent more
+       than one recipe from working. You can fix this by either setting PN to
+       have a value similar to what OpenEmbedded and BitBake use in the default
+       bitbake.conf file (see previous example). Or, by manually updating each
+       recipe to set PN . You will also need to include PN as part of the STAMP
+       , T , and B variable definitions in the local.conf file.
+
+    The ``TMPDIR`` variable establishes a directory that BitBake uses
+    for build output and intermediate files other than the cached
+    information used by the
+    :ref:`bitbake-user-manual/bitbake-user-manual-execution:setscene`
+    process. Here, the ``TMPDIR`` directory is set to ``hello/tmp``.
+
+    .. tip::
+
+       You can always safely delete the tmp directory in order to rebuild a
+       BitBake target. The build process creates the directory for you when you
+       run BitBake.
+
+    For information about each of the other variables defined in this
+    example, check :term:`PN`, :term:`TOPDIR`, :term:`CACHE`, :term:`STAMP`,
+    :term:`T` or :term:`B` to take you to the definitions in the
+    glossary.
+
+#.  **Run BitBake:** After making sure that the ``conf/bitbake.conf`` file
+    exists, you can run the ``bitbake`` command again: ::
+
+       $ bitbake
+       ERROR: Traceback (most recent call last):
+         File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
+           return func(fn, *args)
+         File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 177, in _inherit
+           bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data)
+         File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py", line 92, in inherit
+           include(fn, file, lineno, d, "inherit")
+         File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 100, in include
+           raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), oldfn, lineno)
+       ParseError: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
+
+       ERROR: Unable to parse base: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
+
+    In the sample output,
+    BitBake could not find the ``classes/base.bbclass`` file. You need
+    to create that file next.
+
+#.  **Creating classes/base.bbclass:** BitBake uses class files to
+    provide common code and functionality. The minimally required class
+    for BitBake is the ``classes/base.bbclass`` file. The ``base`` class
+    is implicitly inherited by every recipe. BitBake looks for the class
+    in the ``classes`` directory of the project (i.e ``hello/classes``
+    in this example).
+
+    Create the ``classes`` directory as follows: ::
+
+      $ cd $HOME/hello
+      $ mkdir classes
+
+    Move to the ``classes`` directory and then create the
+    ``base.bbclass`` file by inserting this single line: addtask build
+    The minimal task that BitBake runs is the ``do_build`` task. This is
+    all the example needs in order to build the project. Of course, the
+    ``base.bbclass`` can have much more depending on which build
+    environments BitBake is supporting.
+
+#.  **Run BitBake:** After making sure that the ``classes/base.bbclass``
+    file exists, you can run the ``bitbake`` command again: ::
+
+       $ bitbake
+       Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
+
+    BitBake is finally reporting
+    no errors. However, you can see that it really does not have
+    anything to do. You need to create a recipe that gives BitBake
+    something to do.
+
+#.  **Creating a Layer:** While it is not really necessary for such a
+    small example, it is good practice to create a layer in which to
+    keep your code separate from the general metadata used by BitBake.
+    Thus, this example creates and uses a layer called "mylayer".
+
+    .. note::
+
+       You can find additional information on layers in the
+       ":ref:`bitbake-user-manual/bitbake-user-manual-intro:Layers`" section.
+
+    Minimally, you need a recipe file and a layer configuration file in
+    your layer. The configuration file needs to be in the ``conf``
+    directory inside the layer. Use these commands to set up the layer
+    and the ``conf`` directory: ::
+
+       $ cd $HOME
+       $ mkdir mylayer
+       $ cd mylayer
+       $ mkdir conf
+
+    Move to the ``conf`` directory and create a ``layer.conf`` file that has the
+    following: ::
+
+      BBPATH .= ":${LAYERDIR}"
+      BBFILES += "${LAYERDIR}/\*.bb"
+      BBFILE_COLLECTIONS += "mylayer"
+     `BBFILE_PATTERN_mylayer := "^${LAYERDIR_RE}/"
+
+    For information on these variables, click on :term:`BBFILES`,
+    :term:`LAYERDIR`, :term:`BBFILE_COLLECTIONS` or :term:`BBFILE_PATTERN_mylayer <BBFILE_PATTERN>`
+    to go to the definitions in the glossary.
+
+    You need to create the recipe file next. Inside your layer at the
+    top-level, use an editor and create a recipe file named
+    ``printhello.bb`` that has the following: ::
+
+       DESCRIPTION = "Prints Hello World"
+       PN = 'printhello'
+       PV = '1'
+
+       python do_build() {
+          bb.plain("********************");
+          bb.plain("*                  *");
+          bb.plain("*  Hello, World!   *");
+          bb.plain("*                  *");
+          bb.plain("********************");
+       }
+
+    The recipe file simply provides
+    a description of the recipe, the name, version, and the ``do_build``
+    task, which prints out "Hello World" to the console. For more
+    information on :term:`DESCRIPTION`, :term:`PN` or :term:`PV`
+    follow the links to the glossary.
+
+#. **Run BitBake With a Target:** Now that a BitBake target exists, run
+    the command and provide that target: ::
+
+      $ cd $HOME/hello
+      $ bitbake printhello
+      ERROR: no recipe files to build, check your BBPATH and BBFILES?
+
+      Summary: There was 1 ERROR message shown, returning a non-zero exit code.
+
+    We have created the layer with the recipe and
+    the layer configuration file but it still seems that BitBake cannot
+    find the recipe. BitBake needs a ``conf/bblayers.conf`` that lists
+    the layers for the project. Without this file, BitBake cannot find
+    the recipe.
+
+#. **Creating conf/bblayers.conf:** BitBake uses the
+    ``conf/bblayers.conf`` file to locate layers needed for the project.
+    This file must reside in the ``conf`` directory of the project (i.e.
+    ``hello/conf`` for this example).
+
+    Set your working directory to the ``hello/conf`` directory and then
+    create the ``bblayers.conf`` file so that it contains the following: ::
+
+       BBLAYERS ?= " \
+           /home/<you>/mylayer \
+       "
+
+    You need to provide your own information for ``you`` in the file.
+
+#. **Run BitBake With a Target:** Now that you have supplied the
+    ``bblayers.conf`` file, run the ``bitbake`` command and provide the
+    target: ::
+
+       $ bitbake printhello
+       Parsing recipes: 100% |##################################################################################|
+       Time: 00:00:00
+       Parsing of 1 .bb files complete (0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors.
+       NOTE: Resolving any missing task queue dependencies
+       NOTE: Preparing RunQueue
+       NOTE: Executing RunQueue Tasks
+       ********************
+       *                  *
+       *  Hello, World!   *
+       *                  *
+       ********************
+       NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
+
+    .. note::
+
+       After the first execution, re-running bitbake printhello again will not
+       result in a BitBake run that prints the same console output. The reason
+       for this is that the first time the printhello.bb recipe's do_build task
+       executes successfully, BitBake writes a stamp file for the task. Thus,
+       the next time you attempt to run the task using that same bitbake
+       command, BitBake notices the stamp and therefore determines that the task
+       does not need to be re-run. If you delete the tmp directory or run
+       bitbake -c clean printhello and then re-run the build, the "Hello,
+       World!" message will be printed again.
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
deleted file mode 100644
index 11eb36aa..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
+++ /dev/null
@@ -1,513 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<appendix id='hello-world-example'>
-    <title>Hello World Example</title>
-
-    <section id='bitbake-hello-world'>
-        <title>BitBake Hello World</title>
-
-        <para>
-            The simplest example commonly used to demonstrate any new
-            programming language or tool is the
-            "<ulink url="http://en.wikipedia.org/wiki/Hello_world_program">Hello World</ulink>"
-            example.
-            This appendix demonstrates, in tutorial form, Hello
-            World within the context of BitBake.
-            The tutorial describes how to create a new project
-            and the applicable metadata files necessary to allow
-            BitBake to build it.
-        </para>
-    </section>
-
-    <section id='example-obtaining-bitbake'>
-        <title>Obtaining BitBake</title>
-
-        <para>
-            See the
-            "<link linkend='obtaining-bitbake'>Obtaining BitBake</link>"
-            section for information on how to obtain BitBake.
-            Once you have the source code on your machine, the BitBake directory
-            appears as follows:
-            <literallayout class='monospaced'>
-     $ ls -al
-     total 100
-     drwxrwxr-x. 9 wmat wmat  4096 Jan 31 13:44 .
-     drwxrwxr-x. 3 wmat wmat  4096 Feb  4 10:45 ..
-     -rw-rw-r--. 1 wmat wmat   365 Nov 26 04:55 AUTHORS
-     drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 bin
-     drwxrwxr-x. 4 wmat wmat  4096 Jan 31 13:44 build
-     -rw-rw-r--. 1 wmat wmat 16501 Nov 26 04:55 ChangeLog
-     drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 classes
-     drwxrwxr-x. 2 wmat wmat  4096 Nov 26 04:55 conf
-     drwxrwxr-x. 3 wmat wmat  4096 Nov 26 04:55 contrib
-     -rw-rw-r--. 1 wmat wmat 17987 Nov 26 04:55 COPYING
-     drwxrwxr-x. 3 wmat wmat  4096 Nov 26 04:55 doc
-     -rw-rw-r--. 1 wmat wmat    69 Nov 26 04:55 .gitignore
-     -rw-rw-r--. 1 wmat wmat   849 Nov 26 04:55 HEADER
-     drwxrwxr-x. 5 wmat wmat  4096 Jan 31 13:44 lib
-     -rw-rw-r--. 1 wmat wmat   195 Nov 26 04:55 MANIFEST.in
-     -rw-rw-r--. 1 wmat wmat  2887 Nov 26 04:55 TODO
-            </literallayout>
-        </para>
-
-        <para>
-            At this point, you should have BitBake cloned to
-            a directory that matches the previous listing except for
-            dates and user names.
-        </para>
-    </section>
-
-    <section id='setting-up-the-bitbake-environment'>
-        <title>Setting Up the BitBake Environment</title>
-
-        <para>
-            First, you need to be sure that you can run BitBake.
-            Set your working directory to where your local BitBake
-            files are and run the following command:
-            <literallayout class='monospaced'>
-     $ ./bin/bitbake --version
-     BitBake Build Tool Core version 1.23.0, bitbake version 1.23.0
-            </literallayout>
-            The console output tells you what version you are running.
-        </para>
-
-        <para>
-            The recommended method to run BitBake is from a directory of your
-            choice.
-            To be able to run BitBake from any directory, you need to add the
-            executable binary to your binary to your shell's environment
-            <filename>PATH</filename> variable.
-            First, look at your current <filename>PATH</filename> variable
-            by entering the following:
-            <literallayout class='monospaced'>
-     $ echo $PATH
-            </literallayout>
-            Next, add the directory location for the BitBake binary to the
-            <filename>PATH</filename>.
-            Here is an example that adds the
-            <filename>/home/scott-lenovo/bitbake/bin</filename> directory
-            to the front of the <filename>PATH</filename> variable:
-            <literallayout class='monospaced'>
-     $ export PATH=/home/scott-lenovo/bitbake/bin:$PATH
-            </literallayout>
-            You should now be able to enter the <filename>bitbake</filename>
-            command from the command line while working from any directory.
-        </para>
-    </section>
-
-    <section id='the-hello-world-example'>
-        <title>The Hello World Example</title>
-
-        <para>
-            The overall goal of this exercise is to build a
-            complete "Hello World" example utilizing task and layer
-            concepts.
-            Because this is how modern projects such as OpenEmbedded and
-            the Yocto Project utilize BitBake, the example
-            provides an excellent starting point for understanding
-            BitBake.
-        </para>
-
-        <para>
-            To help you understand how to use BitBake to build targets,
-            the example starts with nothing but the <filename>bitbake</filename>
-            command, which causes BitBake to fail and report problems.
-            The example progresses by adding pieces to the build to
-            eventually conclude with a working, minimal "Hello World"
-            example.
-        </para>
-
-        <para>
-            While every attempt is made to explain what is happening during
-            the example, the descriptions cannot cover everything.
-            You can find further information throughout this manual.
-            Also, you can actively participate in the
-            <ulink url='http://lists.openembedded.org/mailman/listinfo/bitbake-devel'></ulink>
-            discussion mailing list about the BitBake build tool.
-        </para>
-
-        <note>
-            This example was inspired by and drew heavily from
-            <ulink url="http://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html">Mailing List post - The BitBake equivalent of "Hello, World!"</ulink>.
-        </note>
-
-        <para>
-            As stated earlier, the goal of this example
-            is to eventually compile "Hello World".
-            However, it is unknown what BitBake needs and what you have
-            to provide in order to achieve that goal.
-            Recall that BitBake utilizes three types of metadata files:
-            <link linkend='configuration-files'>Configuration Files</link>,
-            <link linkend='classes'>Classes</link>, and
-            <link linkend='recipes'>Recipes</link>.
-            But where do they go?
-            How does BitBake find them?
-            BitBake's error messaging helps you answer these types of questions
-            and helps you better understand exactly what is going on.
-        </para>
-
-        <para>
-            Following is the complete "Hello World" example.
-        </para>
-
-        <orderedlist>
-            <listitem><para><emphasis>Create a Project Directory:</emphasis>
-                First, set up a directory for the "Hello World" project.
-                Here is how you can do so in your home directory:
-                <literallayout class='monospaced'>
-     $ mkdir ~/hello
-     $ cd ~/hello
-                </literallayout>
-                This is the directory that BitBake will use to do all of
-                its work.
-                You can use this directory to keep all the metafiles needed
-                by BitBake.
-                Having a project directory is a good way to isolate your
-                project.
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake:</emphasis>
-                At this point, you have nothing but a project directory.
-                Run the <filename>bitbake</filename> command and see what
-                it does:
-                <literallayout class='monospaced'>
-     $ bitbake
-     The BBPATH variable is not set and bitbake did not
-     find a conf/bblayers.conf file in the expected location.
-     Maybe you accidentally invoked bitbake from the wrong directory?
-     DEBUG: Removed the following variables from the environment:
-     GNOME_DESKTOP_SESSION_ID, XDG_CURRENT_DESKTOP,
-     GNOME_KEYRING_CONTROL, DISPLAY, SSH_AGENT_PID, LANG, no_proxy,
-     XDG_SESSION_PATH, XAUTHORITY, SESSION_MANAGER, SHLVL,
-     MANDATORY_PATH, COMPIZ_CONFIG_PROFILE, WINDOWID, EDITOR,
-     GPG_AGENT_INFO, SSH_AUTH_SOCK, GDMSESSION, GNOME_KEYRING_PID,
-     XDG_SEAT_PATH, XDG_CONFIG_DIRS, LESSOPEN, DBUS_SESSION_BUS_ADDRESS,
-     _, XDG_SESSION_COOKIE, DESKTOP_SESSION, LESSCLOSE, DEFAULTS_PATH,
-     UBUNTU_MENUPROXY, OLDPWD, XDG_DATA_DIRS, COLORTERM, LS_COLORS
-                </literallayout>
-                The majority of this output is specific to environment variables
-                that are not directly relevant to BitBake.
-                However, the very first message regarding the
-                <filename>BBPATH</filename> variable and the
-                <filename>conf/bblayers.conf</filename> file
-                is relevant.</para>
-                <para>
-                When you run BitBake, it begins looking for metadata files.
-                The
-                <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
-                variable is what tells BitBake where to look for those files.
-                <filename>BBPATH</filename> is not set and you need to set it.
-                Without <filename>BBPATH</filename>, BitBake cannot
-                find any configuration files (<filename>.conf</filename>)
-                or recipe files (<filename>.bb</filename>) at all.
-                BitBake also cannot find the <filename>bitbake.conf</filename>
-                file.
-                </para></listitem>
-            <listitem><para><emphasis>Setting <filename>BBPATH</filename>:</emphasis>
-                For this example, you can set <filename>BBPATH</filename>
-                in the same manner that you set <filename>PATH</filename>
-                earlier in the appendix.
-                You should realize, though, that it is much more flexible to set the
-                <filename>BBPATH</filename> variable up in a configuration
-                file for each project.</para>
-                <para>From your shell, enter the following commands to set and
-                export the <filename>BBPATH</filename> variable:
-                <literallayout class='monospaced'>
-     $ BBPATH="<replaceable>projectdirectory</replaceable>"
-     $ export BBPATH
-                </literallayout>
-                Use your actual project directory in the command.
-                BitBake uses that directory to find the metadata it needs for
-                your project.
-                <note>
-                    When specifying your project directory, do not use the
-                    tilde ("~") character as BitBake does not expand that character
-                    as the shell would.
-                </note>
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake:</emphasis>
-                Now that you have <filename>BBPATH</filename> defined, run
-                the <filename>bitbake</filename> command again:
-                <literallayout class='monospaced'>
-     $ bitbake
-     ERROR: Traceback (most recent call last):
-       File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
-         return func(fn, *args)
-       File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 173, in parse_config_file
-         return bb.parse.handle(fn, data, include)
-       File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 99, in handle
-         return h['handle'](fn, data, include)
-       File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 120, in handle
-         abs_fn = resolve_file(fn, data)
-       File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 117, in resolve_file
-         raise IOError("file %s not found in %s" % (fn, bbpath))
-     IOError: file conf/bitbake.conf not found in /home/scott-lenovo/hello
-
-     ERROR: Unable to parse conf/bitbake.conf: file conf/bitbake.conf not found in /home/scott-lenovo/hello
-                </literallayout>
-                This sample output shows that BitBake could not find the
-                <filename>conf/bitbake.conf</filename> file in the project
-                directory.
-                This file is the first thing BitBake must find in order
-                to build a target.
-                And, since the project directory for this example is
-                empty, you need to provide a <filename>conf/bitbake.conf</filename>
-                file.
-                </para></listitem>
-            <listitem><para><emphasis>Creating <filename>conf/bitbake.conf</filename>:</emphasis>
-                The <filename>conf/bitbake.conf</filename> includes a number of
-                configuration variables BitBake uses for metadata and recipe
-                files.
-                For this example, you need to create the file in your project directory
-                and define some key BitBake variables.
-                For more information on the <filename>bitbake.conf</filename> file,
-                see
-                <ulink url='http://git.openembedded.org/bitbake/tree/conf/bitbake.conf'></ulink>.
-                </para>
-                <para>Use the following commands to create the <filename>conf</filename>
-                directory in the project directory:
-                <literallayout class='monospaced'>
-     $ mkdir conf
-                </literallayout>
-                From within the <filename>conf</filename> directory, use
-                some editor to create the <filename>bitbake.conf</filename>
-                so that it contains the following:
-                <literallayout class='monospaced'>
-     <link linkend='var-bb-PN'>PN</link>  = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
-                </literallayout>
-                <literallayout class='monospaced'>
-     TMPDIR  = "${<link linkend='var-bb-TOPDIR'>TOPDIR</link>}/tmp"
-     <link linkend='var-bb-CACHE'>CACHE</link>   = "${TMPDIR}/cache"
-     <link linkend='var-bb-STAMP'>STAMP</link>   = "${TMPDIR}/${PN}/stamps"
-     <link linkend='var-bb-T'>T</link>       = "${TMPDIR}/${PN}/work"
-     <link linkend='var-bb-B'>B</link>       = "${TMPDIR}/${PN}"
-                </literallayout>
-                <note>
-                    Without a value for <filename>PN</filename>, the
-                    variables <filename>STAMP</filename>,
-                    <filename>T</filename>, and <filename>B</filename>,
-                    prevent more than one recipe from working. You can fix
-                    this by either setting <filename>PN</filename> to have
-                    a value similar to what OpenEmbedded and BitBake use
-                    in the default <filename>bitbake.conf</filename> file
-                    (see previous example). Or, by manually updating each
-                    recipe to set <filename>PN</filename>. You will also
-                    need to include <filename>PN</filename> as part of the
-                    <filename>STAMP</filename>, <filename>T</filename>, and
-                    <filename>B</filename> variable definitions in the
-                    <filename>local.conf</filename> file.
-                </note>
-                The <filename>TMPDIR</filename> variable establishes a directory
-                that BitBake uses for build output and intermediate files other
-                than the cached information used by the
-                <link linkend='setscene'>Setscene</link> process.
-                Here, the <filename>TMPDIR</filename> directory is set to
-                <filename>hello/tmp</filename>.
-                <note><title>Tip</title>
-                    You can always safely delete the <filename>tmp</filename>
-                    directory in order to rebuild a BitBake target.
-                    The build process creates the directory for you
-                    when you run BitBake.
-                </note></para>
-                <para>For information about each of the other variables defined in this
-                example, click on the links to take you to the definitions in
-                the glossary.
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake:</emphasis>
-                After making sure that the <filename>conf/bitbake.conf</filename>
-                file exists, you can run the <filename>bitbake</filename>
-                command again:
-                <literallayout class='monospaced'>
-     $ bitbake
-     ERROR: Traceback (most recent call last):
-       File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
-         return func(fn, *args)
-       File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 177, in _inherit
-         bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data)
-       File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py", line 92, in inherit
-         include(fn, file, lineno, d, "inherit")
-       File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 100, in include
-         raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), oldfn, lineno)
-     ParseError: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
-
-     ERROR: Unable to parse base: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
-                </literallayout>
-                In the sample output, BitBake could not find the
-                <filename>classes/base.bbclass</filename> file.
-                You need to create that file next.
-                </para></listitem>
-            <listitem><para><emphasis>Creating <filename>classes/base.bbclass</filename>:</emphasis>
-                BitBake uses class files to provide common code and functionality.
-                The minimally required class for BitBake is the
-                <filename>classes/base.bbclass</filename> file.
-                The <filename>base</filename> class is implicitly inherited by
-                every recipe.
-                BitBake looks for the class in the <filename>classes</filename>
-                directory of the project (i.e <filename>hello/classes</filename>
-                in this example).
-                </para>
-                <para>Create the <filename>classes</filename> directory as follows:
-                <literallayout class='monospaced'>
-     $ cd $HOME/hello
-     $ mkdir classes
-                </literallayout>
-                Move to the <filename>classes</filename> directory and then
-                create the <filename>base.bbclass</filename> file by inserting
-                this single line:
-                <literallayout class='monospaced'>
-     addtask build
-                </literallayout>
-                The minimal task that BitBake runs is the
-                <filename>do_build</filename> task.
-                This is all the example needs in order to build the project.
-                Of course, the <filename>base.bbclass</filename> can have much
-                more depending on which build environments BitBake is
-                supporting.
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake:</emphasis>
-                After making sure that the <filename>classes/base.bbclass</filename>
-                file exists, you can run the <filename>bitbake</filename>
-                command again:
-                <literallayout class='monospaced'>
-     $ bitbake
-     Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
-                </literallayout>
-                BitBake is finally reporting no errors.
-                However, you can see that it really does not have anything
-                to do.
-                You need to create a recipe that gives BitBake something to do.
-                </para></listitem>
-            <listitem><para><emphasis>Creating a Layer:</emphasis>
-                While it is not really necessary for such a small example,
-                it is good practice to create a layer in which to keep your
-                code separate from the general metadata used by BitBake.
-                Thus, this example creates and uses a layer called "mylayer".
-                <note>
-                    You can find additional information on layers in the
-                    "<link linkend='layers'>Layers</link>" section.
-                </note></para>
-
-                <para>Minimally, you need a recipe file and a layer configuration
-                file in your layer.
-                The configuration file needs to be in the <filename>conf</filename>
-                directory inside the layer.
-                Use these commands to set up the layer and the <filename>conf</filename>
-                directory:
-                <literallayout class='monospaced'>
-     $ cd $HOME
-     $ mkdir mylayer
-     $ cd mylayer
-     $ mkdir conf
-                </literallayout>
-                Move to the <filename>conf</filename> directory and create a
-                <filename>layer.conf</filename> file that has the following:
-                <literallayout class='monospaced'>
-     BBPATH .= ":${<link linkend='var-bb-LAYERDIR'>LAYERDIR</link>}"
-
-     <link linkend='var-bb-BBFILES'>BBFILES</link> += "${LAYERDIR}/*.bb"
-
-     <link linkend='var-bb-BBFILE_COLLECTIONS'>BBFILE_COLLECTIONS</link> += "mylayer"
-     <link linkend='var-bb-BBFILE_PATTERN'>BBFILE_PATTERN_mylayer</link> := "^${LAYERDIR_RE}/"
-                </literallayout>
-                For information on these variables, click the links
-                to go to the definitions in the glossary.</para>
-                <para>You need to create the recipe file next.
-                Inside your layer at the top-level, use an editor and create
-                a recipe file named <filename>printhello.bb</filename> that
-                has the following:
-                <literallayout class='monospaced'>
-     <link linkend='var-bb-DESCRIPTION'>DESCRIPTION</link> = "Prints Hello World"
-     <link linkend='var-bb-PN'>PN</link> = 'printhello'
-     <link linkend='var-bb-PV'>PV</link> = '1'
-
-     python do_build() {
-        bb.plain("********************");
-        bb.plain("*                  *");
-        bb.plain("*  Hello, World!   *");
-        bb.plain("*                  *");
-        bb.plain("********************");
-     }
-                </literallayout>
-                The recipe file simply provides a description of the
-                recipe, the name, version, and the <filename>do_build</filename>
-                task, which prints out "Hello World" to the console.
-                For more information on these variables, follow the links
-                to the glossary.
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake With a Target:</emphasis>
-                Now that a BitBake target exists, run the command and provide
-                that target:
-                <literallayout class='monospaced'>
-     $ cd $HOME/hello
-     $ bitbake printhello
-     ERROR: no recipe files to build, check your BBPATH and BBFILES?
-
-     Summary: There was 1 ERROR message shown, returning a non-zero exit code.
-                </literallayout>
-                We have created the layer with the recipe and the layer
-                configuration file but it still seems that BitBake cannot
-                find the recipe.
-                BitBake needs a <filename>conf/bblayers.conf</filename> that
-                lists the layers for the project.
-                Without this file, BitBake cannot find the recipe.
-                </para></listitem>
-            <listitem><para><emphasis>Creating <filename>conf/bblayers.conf</filename>:</emphasis>
-                BitBake uses the <filename>conf/bblayers.conf</filename> file
-                to locate layers needed for the project.
-                This file must reside in the <filename>conf</filename> directory
-                of the project (i.e. <filename>hello/conf</filename> for this
-                example).</para>
-                <para>Set your working directory to the <filename>hello/conf</filename>
-                directory and then create the <filename>bblayers.conf</filename>
-                file so that it contains the following:
-                <literallayout class='monospaced'>
-     BBLAYERS ?= " \
-       /home/&lt;you&gt;/mylayer \
-       "
-                </literallayout>
-                You need to provide your own information for
-                <filename>you</filename> in the file.
-                </para></listitem>
-            <listitem><para><emphasis>Run BitBake With a Target:</emphasis>
-                Now that you have supplied the <filename>bblayers.conf</filename>
-                file, run the <filename>bitbake</filename> command and provide
-                the target:
-                <literallayout class='monospaced'>
-     $ bitbake printhello
-     Parsing recipes: 100% |##################################################################################|
-     Time: 00:00:00
-     Parsing of 1 .bb files complete (0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors.
-     NOTE: Resolving any missing task queue dependencies
-     NOTE: Preparing RunQueue
-     NOTE: Executing RunQueue Tasks
-     ********************
-     *                  *
-     *  Hello, World!   *
-     *                  *
-     ********************
-     NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
-                </literallayout>
-                BitBake finds the <filename>printhello</filename> recipe and
-                successfully runs the task.
-                <note>
-                    After the first execution, re-running
-                    <filename>bitbake printhello</filename> again will not
-                    result in a BitBake run that prints the same console
-                    output.
-                    The reason for this is that the first time the
-                    <filename>printhello.bb</filename> recipe's
-                    <filename>do_build</filename> task executes
-                    successfully, BitBake writes a stamp file for the task.
-                    Thus, the next time you attempt to run the task
-                    using that same <filename>bitbake</filename> command,
-                    BitBake notices the stamp and therefore determines
-                    that the task does not need to be re-run.
-                    If you delete the <filename>tmp</filename> directory
-                    or run <filename>bitbake -c clean printhello</filename>
-                    and then re-run the build, the "Hello, World!" message will
-                    be printed again.
-                </note>
-                </para></listitem>
-        </orderedlist>
-    </section>
-</appendix>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.rst
new file mode 100644
index 00000000..6f9d3929
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.rst
@@ -0,0 +1,651 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+========
+Overview
+========
+
+|
+
+Welcome to the BitBake User Manual. This manual provides information on
+the BitBake tool. The information attempts to be as independent as
+possible regarding systems that use BitBake, such as OpenEmbedded and
+the Yocto Project. In some cases, scenarios or examples within the
+context of a build system are used in the manual to help with
+understanding. For these cases, the manual clearly states the context.
+
+.. _intro:
+
+Introduction
+============
+
+Fundamentally, BitBake is a generic task execution engine that allows
+shell and Python tasks to be run efficiently and in parallel while
+working within complex inter-task dependency constraints. One of
+BitBake's main users, OpenEmbedded, takes this core and builds embedded
+Linux software stacks using a task-oriented approach.
+
+Conceptually, BitBake is similar to GNU Make in some regards but has
+significant differences:
+
+-  BitBake executes tasks according to provided metadata that builds up
+   the tasks. Metadata is stored in recipe (``.bb``) and related recipe
+   "append" (``.bbappend``) files, configuration (``.conf``) and
+   underlying include (``.inc``) files, and in class (``.bbclass``)
+   files. The metadata provides BitBake with instructions on what tasks
+   to run and the dependencies between those tasks.
+
+-  BitBake includes a fetcher library for obtaining source code from
+   various places such as local files, source control systems, or
+   websites.
+
+-  The instructions for each unit to be built (e.g. a piece of software)
+   are known as "recipe" files and contain all the information about the
+   unit (dependencies, source file locations, checksums, description and
+   so on).
+
+-  BitBake includes a client/server abstraction and can be used from a
+   command line or used as a service over XML-RPC and has several
+   different user interfaces.
+
+History and Goals
+=================
+
+BitBake was originally a part of the OpenEmbedded project. It was
+inspired by the Portage package management system used by the Gentoo
+Linux distribution. On December 7, 2004, OpenEmbedded project team
+member Chris Larson split the project into two distinct pieces:
+
+-  BitBake, a generic task executor
+
+-  OpenEmbedded, a metadata set utilized by BitBake
+
+Today, BitBake is the primary basis of the
+`OpenEmbedded <http://www.openembedded.org/>`__ project, which is being
+used to build and maintain Linux distributions such as the `Angstrom
+Distribution <http://www.angstrom-distribution.org/>`__, and which is
+also being used as the build tool for Linux projects such as the `Yocto
+Project <http://www.yoctoproject.org>`__.
+
+Prior to BitBake, no other build tool adequately met the needs of an
+aspiring embedded Linux distribution. All of the build systems used by
+traditional desktop Linux distributions lacked important functionality,
+and none of the ad hoc Buildroot-based systems, prevalent in the
+embedded space, were scalable or maintainable.
+
+Some important original goals for BitBake were:
+
+-  Handle cross-compilation.
+
+-  Handle inter-package dependencies (build time on target architecture,
+   build time on native architecture, and runtime).
+
+-  Support running any number of tasks within a given package,
+   including, but not limited to, fetching upstream sources, unpacking
+   them, patching them, configuring them, and so forth.
+
+-  Be Linux distribution agnostic for both build and target systems.
+
+-  Be architecture agnostic.
+
+-  Support multiple build and target operating systems (e.g. Cygwin, the
+   BSDs, and so forth).
+
+-  Be self-contained, rather than tightly integrated into the build
+   machine's root filesystem.
+
+-  Handle conditional metadata on the target architecture, operating
+   system, distribution, and machine.
+
+-  Be easy to use the tools to supply local metadata and packages
+   against which to operate.
+
+-  Be easy to use BitBake to collaborate between multiple projects for
+   their builds.
+
+-  Provide an inheritance mechanism to share common metadata between
+   many packages.
+
+Over time it became apparent that some further requirements were
+necessary:
+
+-  Handle variants of a base recipe (e.g. native, sdk, and multilib).
+
+-  Split metadata into layers and allow layers to enhance or override
+   other layers.
+
+-  Allow representation of a given set of input variables to a task as a
+   checksum. Based on that checksum, allow acceleration of builds with
+   prebuilt components.
+
+BitBake satisfies all the original requirements and many more with
+extensions being made to the basic functionality to reflect the
+additional requirements. Flexibility and power have always been the
+priorities. BitBake is highly extensible and supports embedded Python
+code and execution of any arbitrary tasks.
+
+.. _Concepts:
+
+Concepts
+========
+
+BitBake is a program written in the Python language. At the highest
+level, BitBake interprets metadata, decides what tasks are required to
+run, and executes those tasks. Similar to GNU Make, BitBake controls how
+software is built. GNU Make achieves its control through "makefiles",
+while BitBake uses "recipes".
+
+BitBake extends the capabilities of a simple tool like GNU Make by
+allowing for the definition of much more complex tasks, such as
+assembling entire embedded Linux distributions.
+
+The remainder of this section introduces several concepts that should be
+understood in order to better leverage the power of BitBake.
+
+Recipes
+-------
+
+BitBake Recipes, which are denoted by the file extension ``.bb``, are
+the most basic metadata files. These recipe files provide BitBake with
+the following:
+
+-  Descriptive information about the package (author, homepage, license,
+   and so on)
+
+-  The version of the recipe
+
+-  Existing dependencies (both build and runtime dependencies)
+
+-  Where the source code resides and how to fetch it
+
+-  Whether the source code requires any patches, where to find them, and
+   how to apply them
+
+-  How to configure and compile the source code
+
+-  How to assemble the generated artifacts into one or more installable
+   packages
+
+-  Where on the target machine to install the package or packages
+   created
+
+Within the context of BitBake, or any project utilizing BitBake as its
+build system, files with the ``.bb`` extension are referred to as
+recipes.
+
+.. note::
+
+   The term "package" is also commonly used to describe recipes.
+   However, since the same word is used to describe packaged output from
+   a project, it is best to maintain a single descriptive term -
+   "recipes". Put another way, a single "recipe" file is quite capable
+   of generating a number of related but separately installable
+   "packages". In fact, that ability is fairly common.
+
+Configuration Files
+-------------------
+
+Configuration files, which are denoted by the ``.conf`` extension,
+define various configuration variables that govern the project's build
+process. These files fall into several areas that define machine
+configuration, distribution configuration, possible compiler tuning,
+general common configuration, and user configuration. The main
+configuration file is the sample ``bitbake.conf`` file, which is located
+within the BitBake source tree ``conf`` directory.
+
+Classes
+-------
+
+Class files, which are denoted by the ``.bbclass`` extension, contain
+information that is useful to share between metadata files. The BitBake
+source tree currently comes with one class metadata file called
+``base.bbclass``. You can find this file in the ``classes`` directory.
+The ``base.bbclass`` class files is special since it is always included
+automatically for all recipes and classes. This class contains
+definitions for standard basic tasks such as fetching, unpacking,
+configuring (empty by default), compiling (runs any Makefile present),
+installing (empty by default) and packaging (empty by default). These
+tasks are often overridden or extended by other classes added during the
+project development process.
+
+Layers
+------
+
+Layers allow you to isolate different types of customizations from each
+other. While you might find it tempting to keep everything in one layer
+when working on a single project, the more modular your metadata, the
+easier it is to cope with future changes.
+
+To illustrate how you can use layers to keep things modular, consider
+customizations you might make to support a specific target machine.
+These types of customizations typically reside in a special layer,
+rather than a general layer, called a Board Support Package (BSP) layer.
+Furthermore, the machine customizations should be isolated from recipes
+and metadata that support a new GUI environment, for example. This
+situation gives you a couple of layers: one for the machine
+configurations and one for the GUI environment. It is important to
+understand, however, that the BSP layer can still make machine-specific
+additions to recipes within the GUI environment layer without polluting
+the GUI layer itself with those machine-specific changes. You can
+accomplish this through a recipe that is a BitBake append
+(``.bbappend``) file.
+
+.. _append-bbappend-files:
+
+Append Files
+------------
+
+Append files, which are files that have the ``.bbappend`` file
+extension, extend or override information in an existing recipe file.
+
+BitBake expects every append file to have a corresponding recipe file.
+Furthermore, the append file and corresponding recipe file must use the
+same root filename. The filenames can differ only in the file type
+suffix used (e.g. ``formfactor_0.0.bb`` and
+``formfactor_0.0.bbappend``).
+
+Information in append files extends or overrides the information in the
+underlying, similarly-named recipe files.
+
+When you name an append file, you can use the "``%``" wildcard character
+to allow for matching recipe names. For example, suppose you have an
+append file named as follows: ::
+
+  busybox_1.21.%.bbappend
+
+That append file
+would match any ``busybox_1.21.``\ x\ ``.bb`` version of the recipe. So,
+the append file would match the following recipe names: ::
+
+  busybox_1.21.1.bb
+  busybox_1.21.2.bb
+  busybox_1.21.3.bb
+
+.. note::
+
+   The use of the " % " character is limited in that it only works directly in
+   front of the .bbappend portion of the append file's name. You cannot use the
+   wildcard character in any other location of the name.
+
+If the ``busybox`` recipe was updated to ``busybox_1.3.0.bb``, the
+append name would not match. However, if you named the append file
+``busybox_1.%.bbappend``, then you would have a match.
+
+In the most general case, you could name the append file something as
+simple as ``busybox_%.bbappend`` to be entirely version independent.
+
+Obtaining BitBake
+=================
+
+You can obtain BitBake several different ways:
+
+-  **Cloning BitBake:** Using Git to clone the BitBake source code
+   repository is the recommended method for obtaining BitBake. Cloning
+   the repository makes it easy to get bug fixes and have access to
+   stable branches and the master branch. Once you have cloned BitBake,
+   you should use the latest stable branch for development since the
+   master branch is for BitBake development and might contain less
+   stable changes.
+
+   You usually need a version of BitBake that matches the metadata you
+   are using. The metadata is generally backwards compatible but not
+   forward compatible.
+
+   Here is an example that clones the BitBake repository: ::
+
+     $ git clone git://git.openembedded.org/bitbake
+
+   This command clones the BitBake
+   Git repository into a directory called ``bitbake``. Alternatively,
+   you can designate a directory after the ``git clone`` command if you
+   want to call the new directory something other than ``bitbake``. Here
+   is an example that names the directory ``bbdev``: ::
+
+     $ git clone git://git.openembedded.org/bitbake bbdev
+
+-  **Installation using your Distribution Package Management System:**
+   This method is not recommended because the BitBake version that is
+   provided by your distribution, in most cases, is several releases
+   behind a snapshot of the BitBake repository.
+
+-  **Taking a snapshot of BitBake:** Downloading a snapshot of BitBake
+   from the source code repository gives you access to a known branch or
+   release of BitBake.
+
+      .. note::
+
+         Cloning the Git repository, as described earlier, is the preferred
+         method for getting BitBake. Cloning the repository makes it easier
+         to update as patches are added to the stable branches.
+
+   The following example downloads a snapshot of BitBake version 1.17.0: ::
+
+     $ wget http://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
+     $ tar zxpvf bitbake-1.17.0.tar.gz
+
+   After extraction of the tarball using
+   the tar utility, you have a directory entitled ``bitbake-1.17.0``.
+
+-  **Using the BitBake that Comes With Your Build Checkout:** A final
+   possibility for getting a copy of BitBake is that it already comes
+   with your checkout of a larger BitBake-based build system, such as
+   Poky. Rather than manually checking out individual layers and gluing
+   them together yourself, you can check out an entire build system. The
+   checkout will already include a version of BitBake that has been
+   thoroughly tested for compatibility with the other components. For
+   information on how to check out a particular BitBake-based build
+   system, consult that build system's supporting documentation.
+
+.. _bitbake-user-manual-command:
+
+The BitBake Command
+===================
+
+The ``bitbake`` command is the primary interface to the BitBake tool.
+This section presents the BitBake command syntax and provides several
+execution examples.
+
+Usage and syntax
+----------------
+
+Following is the usage and syntax for BitBake: ::
+
+   $ bitbake -h
+   Usage: bitbake [options] [recipename/target recipe:do_task ...]
+
+       Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
+       It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
+       will provide the layer, BBFILES and other configuration information.
+
+   Options:
+     --version             show program's version number and exit
+     -h, --help            show this help message and exit
+     -b BUILDFILE, --buildfile=BUILDFILE
+                           Execute tasks from a specific .bb recipe directly.
+                           WARNING: Does not handle any dependencies from other
+                           recipes.
+     -k, --continue        Continue as much as possible after an error. While the
+                           target that failed and anything depending on it cannot
+                           be built, as much as possible will be built before
+                           stopping.
+     -f, --force           Force the specified targets/task to run (invalidating
+                           any existing stamp file).
+     -c CMD, --cmd=CMD     Specify the task to execute. The exact options
+                           available depend on the metadata. Some examples might
+                           be 'compile' or 'populate_sysroot' or 'listtasks' may
+                           give a list of the tasks available.
+     -C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
+                           Invalidate the stamp for the specified task such as
+                           'compile' and then run the default task for the
+                           specified target(s).
+     -r PREFILE, --read=PREFILE
+                           Read the specified file before bitbake.conf.
+     -R POSTFILE, --postread=POSTFILE
+                           Read the specified file after bitbake.conf.
+     -v, --verbose         Enable tracing of shell tasks (with 'set -x'). Also
+                           print bb.note(...) messages to stdout (in addition to
+                           writing them to ${T}/log.do_&lt;task&gt;).
+     -D, --debug           Increase the debug level. You can specify this more
+                           than once. -D sets the debug level to 1, where only
+                           bb.debug(1, ...) messages are printed to stdout; -DD
+                           sets the debug level to 2, where both bb.debug(1, ...)
+                           and bb.debug(2, ...) messages are printed; etc.
+                           Without -D, no debug messages are printed. Note that
+                           -D only affects output to stdout. All debug messages
+                           are written to ${T}/log.do_taskname, regardless of the
+                           debug level.
+     -q, --quiet           Output less log message data to the terminal. You can
+                           specify this more than once.
+     -n, --dry-run         Don't execute, just go through the motions.
+     -S SIGNATURE_HANDLER, --dump-signatures=SIGNATURE_HANDLER
+                           Dump out the signature construction information, with
+                           no task execution. The SIGNATURE_HANDLER parameter is
+                           passed to the handler. Two common values are none and
+                           printdiff but the handler may define more/less. none
+                           means only dump the signature, printdiff means compare
+                           the dumped signature with the cached one.
+     -p, --parse-only      Quit after parsing the BB recipes.
+     -s, --show-versions   Show current and preferred versions of all recipes.
+     -e, --environment     Show the global or per-recipe environment complete
+                           with information about where variables were
+                           set/changed.
+     -g, --graphviz        Save dependency tree information for the specified
+                           targets in the dot syntax.
+     -I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
+                           Assume these dependencies don't exist and are already
+                           provided (equivalent to ASSUME_PROVIDED). Useful to
+                           make dependency graphs more appealing
+     -l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
+                           Show debug logging for the specified logging domains
+     -P, --profile         Profile the command and save reports.
+     -u UI, --ui=UI        The user interface to use (knotty, ncurses or taskexp
+                           - default knotty).
+     --token=XMLRPCTOKEN   Specify the connection token to be used when
+                           connecting to a remote server.
+     --revisions-changed   Set the exit code depending on whether upstream
+                           floating revisions have changed or not.
+     --server-only         Run bitbake without a UI, only starting a server
+                           (cooker) process.
+     -B BIND, --bind=BIND  The name/address for the bitbake xmlrpc server to bind
+                           to.
+     -T SERVER_TIMEOUT, --idle-timeout=SERVER_TIMEOUT
+                           Set timeout to unload bitbake server due to
+                           inactivity, set to -1 means no unload, default:
+                           Environment variable BB_SERVER_TIMEOUT.
+     --no-setscene         Do not run any setscene tasks. sstate will be ignored
+                           and everything needed, built.
+     --setscene-only       Only run setscene tasks, don't run any real tasks.
+     --remote-server=REMOTE_SERVER
+                           Connect to the specified server.
+     -m, --kill-server     Terminate any running bitbake server.
+     --observe-only        Connect to a server as an observing-only client.
+     --status-only         Check the status of the remote bitbake server.
+     -w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
+                           Writes the event log of the build to a bitbake event
+                           json file. Use '' (empty string) to assign the name
+                           automatically.
+     --runall=RUNALL       Run the specified task for any recipe in the taskgraph
+                           of the specified target (even if it wouldn't otherwise
+                           have run).
+     --runonly=RUNONLY     Run only the specified task within the taskgraph of
+                           the specified targets (and any task dependencies those
+                           tasks may have).
+
+.. _bitbake-examples:
+
+Examples
+--------
+
+This section presents some examples showing how to use BitBake.
+
+.. _example-executing-a-task-against-a-single-recipe:
+
+Executing a Task Against a Single Recipe
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Executing tasks for a single recipe file is relatively simple. You
+specify the file in question, and BitBake parses it and executes the
+specified task. If you do not specify a task, BitBake executes the
+default task, which is "build". BitBake obeys inter-task dependencies
+when doing so.
+
+The following command runs the build task, which is the default task, on
+the ``foo_1.0.bb`` recipe file: ::
+
+  $ bitbake -b foo_1.0.bb
+
+The following command runs the clean task on the ``foo.bb`` recipe file: ::
+
+  $ bitbake -b foo.bb -c clean
+
+.. note::
+
+   The "-b" option explicitly does not handle recipe dependencies. Other
+   than for debugging purposes, it is instead recommended that you use
+   the syntax presented in the next section.
+
+Executing Tasks Against a Set of Recipe Files
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are a number of additional complexities introduced when one wants
+to manage multiple ``.bb`` files. Clearly there needs to be a way to
+tell BitBake what files are available and, of those, which you want to
+execute. There also needs to be a way for each recipe to express its
+dependencies, both for build-time and runtime. There must be a way for
+you to express recipe preferences when multiple recipes provide the same
+functionality, or when there are multiple versions of a recipe.
+
+The ``bitbake`` command, when not using "--buildfile" or "-b" only
+accepts a "PROVIDES". You cannot provide anything else. By default, a
+recipe file generally "PROVIDES" its "packagename" as shown in the
+following example: ::
+
+  $ bitbake foo
+
+This next example "PROVIDES" the
+package name and also uses the "-c" option to tell BitBake to just
+execute the ``do_clean`` task: ::
+
+  $ bitbake -c clean foo
+
+Executing a List of Task and Recipe Combinations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The BitBake command line supports specifying different tasks for
+individual targets when you specify multiple targets. For example,
+suppose you had two targets (or recipes) ``myfirstrecipe`` and
+``mysecondrecipe`` and you needed BitBake to run ``taskA`` for the first
+recipe and ``taskB`` for the second recipe: ::
+
+  $ bitbake myfirstrecipe:do_taskA mysecondrecipe:do_taskB
+
+Generating Dependency Graphs
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BitBake is able to generate dependency graphs using the ``dot`` syntax.
+You can convert these graphs into images using the ``dot`` tool from
+`Graphviz <http://www.graphviz.org>`__.
+
+When you generate a dependency graph, BitBake writes two files to the
+current working directory:
+
+-  ``task-depends.dot``: Shows dependencies between tasks. These
+   dependencies match BitBake's internal task execution list.
+
+-  ``pn-buildlist``: Shows a simple list of targets that are to be
+   built.
+
+To stop depending on common depends, use the "-I" depend option and
+BitBake omits them from the graph. Leaving this information out can
+produce more readable graphs. This way, you can remove from the graph
+``DEPENDS`` from inherited classes such as ``base.bbclass``.
+
+Here are two examples that create dependency graphs. The second example
+omits depends common in OpenEmbedded from the graph: ::
+
+  $ bitbake -g foo
+
+  $ bitbake -g -I virtual/kernel -I eglibc foo
+
+Executing a Multiple Configuration Build
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+BitBake is able to build multiple images or packages using a single
+command where the different targets require different configurations
+(multiple configuration builds). Each target, in this scenario, is
+referred to as a "multiconfig".
+
+To accomplish a multiple configuration build, you must define each
+target's configuration separately using a parallel configuration file in
+the build directory. The location for these multiconfig configuration
+files is specific. They must reside in the current build directory in a
+sub-directory of ``conf`` named ``multiconfig``. Following is an example
+for two separate targets:
+
+.. image:: figures/bb_multiconfig_files.png
+   :align: center
+
+The reason for this required file hierarchy is because the ``BBPATH``
+variable is not constructed until the layers are parsed. Consequently,
+using the configuration file as a pre-configuration file is not possible
+unless it is located in the current working directory.
+
+Minimally, each configuration file must define the machine and the
+temporary directory BitBake uses for the build. Suggested practice
+dictates that you do not overlap the temporary directories used during
+the builds.
+
+Aside from separate configuration files for each target, you must also
+enable BitBake to perform multiple configuration builds. Enabling is
+accomplished by setting the
+:term:`BBMULTICONFIG` variable in the
+``local.conf`` configuration file. As an example, suppose you had
+configuration files for ``target1`` and ``target2`` defined in the build
+directory. The following statement in the ``local.conf`` file both
+enables BitBake to perform multiple configuration builds and specifies
+the two extra multiconfigs: ::
+
+  BBMULTICONFIG = "target1 target2"
+
+Once the target configuration files are in place and BitBake has been
+enabled to perform multiple configuration builds, use the following
+command form to start the builds: ::
+
+  $ bitbake [mc:multiconfigname:]target [[[mc:multiconfigname:]target] ... ]
+
+Here is an example for two extra multiconfigs: ``target1`` and ``target2``: ::
+
+  $ bitbake mc::target mc:target1:target mc:target2:target
+
+.. _bb-enabling-multiple-configuration-build-dependencies:
+
+Enabling Multiple Configuration Build Dependencies
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sometimes dependencies can exist between targets (multiconfigs) in a
+multiple configuration build. For example, suppose that in order to
+build an image for a particular architecture, the root filesystem of
+another build for a different architecture needs to exist. In other
+words, the image for the first multiconfig depends on the root
+filesystem of the second multiconfig. This dependency is essentially
+that the task in the recipe that builds one multiconfig is dependent on
+the completion of the task in the recipe that builds another
+multiconfig.
+
+To enable dependencies in a multiple configuration build, you must
+declare the dependencies in the recipe using the following statement
+form: ::
+
+  task_or_package[mcdepends] = "mc:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend"
+
+To better show how to use this statement, consider an example with two
+multiconfigs: ``target1`` and ``target2``: ::
+
+  image_task[mcdepends] = "mc:target1:target2:image2:rootfs_task"
+
+In this example, the
+``from_multiconfig`` is "target1" and the ``to_multiconfig`` is "target2". The
+task on which the image whose recipe contains image_task depends on the
+completion of the rootfs_task used to build out image2, which is
+associated with the "target2" multiconfig.
+
+Once you set up this dependency, you can build the "target1" multiconfig
+using a BitBake command as follows: ::
+
+  $ bitbake mc:target1:image1
+
+This command executes all the tasks needed to create ``image1`` for the "target1"
+multiconfig. Because of the dependency, BitBake also executes through
+the ``rootfs_task`` for the "target2" multiconfig build.
+
+Having a recipe depend on the root filesystem of another build might not
+seem that useful. Consider this change to the statement in the image1
+recipe: ::
+
+  image_task[mcdepends] = "mc:target1:target2:image2:image_task"
+
+In this case, BitBake must create ``image2`` for the "target2" build since
+the "target1" build depends on it.
+
+Because "target1" and "target2" are enabled for multiple configuration
+builds and have separate configuration files, BitBake places the
+artifacts for each build in the respective temporary build directories.
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
deleted file mode 100644
index 995c2fa7..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
+++ /dev/null
@@ -1,891 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<chapter id="bitbake-user-manual-intro">
-    <title>Overview</title>
-
-    <para>
-        Welcome to the BitBake User Manual.
-        This manual provides information on the BitBake tool.
-        The information attempts to be as independent as possible regarding
-        systems that use BitBake, such as OpenEmbedded and the
-        Yocto Project.
-        In some cases, scenarios or examples within the context of
-        a build system are used in the manual to help with understanding.
-        For these cases, the manual clearly states the context.
-    </para>
-
-    <section id="intro">
-        <title>Introduction</title>
-
-        <para>
-            Fundamentally, BitBake is a generic task execution
-            engine that allows shell and Python tasks to be run
-            efficiently and in parallel while working within
-            complex inter-task dependency constraints.
-            One of BitBake's main users, OpenEmbedded, takes this core
-            and builds embedded Linux software stacks using
-            a task-oriented approach.
-        </para>
-
-        <para>
-            Conceptually, BitBake is similar to GNU Make in
-            some regards but has significant differences:
-            <itemizedlist>
-                <listitem><para>
-                    BitBake executes tasks according to provided
-                    metadata that builds up the tasks.
-                    Metadata is stored in recipe (<filename>.bb</filename>)
-                    and related recipe "append" (<filename>.bbappend</filename>)
-                    files, configuration (<filename>.conf</filename>) and
-                    underlying include (<filename>.inc</filename>) files, and
-                    in class (<filename>.bbclass</filename>) files.
-                    The metadata provides
-                    BitBake with instructions on what tasks to run and
-                    the dependencies between those tasks.
-                    </para></listitem>
-                <listitem><para>
-                    BitBake includes a fetcher library for obtaining source
-                    code from various places such as local files, source control
-                    systems, or websites.
-                    </para></listitem>
-                <listitem><para>
-                    The instructions for each unit to be built (e.g. a piece
-                    of software) are known as "recipe" files and
-                    contain all the information about the unit
-                    (dependencies, source file locations, checksums, description
-                    and so on).
-                    </para></listitem>
-                <listitem><para>
-                    BitBake includes a client/server abstraction and can
-                    be used from a command line or used as a service over
-                    XML-RPC and has several different user interfaces.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id="history-and-goals">
-        <title>History and Goals</title>
-
-        <para>
-            BitBake was originally a part of the OpenEmbedded project.
-            It was inspired by the Portage package management system
-            used by the Gentoo Linux distribution.
-            On December 7, 2004, OpenEmbedded project team member
-            Chris Larson split the project into two distinct pieces:
-            <itemizedlist>
-                <listitem><para>BitBake, a generic task executor</para></listitem>
-                <listitem><para>OpenEmbedded, a metadata set utilized by
-                    BitBake</para></listitem>
-            </itemizedlist>
-            Today, BitBake is the primary basis of the
-            <ulink url="http://www.openembedded.org/">OpenEmbedded</ulink>
-            project, which is being used to build and maintain Linux
-            distributions such as the
-            <ulink url='http://www.angstrom-distribution.org/'>Angstrom Distribution</ulink>,
-            and which is also being used as the build tool for Linux projects
-            such as the
-            <ulink url='http://www.yoctoproject.org'>Yocto Project</ulink>.
-        </para>
-
-        <para>
-            Prior to BitBake, no other build tool adequately met the needs of
-            an aspiring embedded Linux distribution.
-            All of the build systems used by traditional desktop Linux
-            distributions lacked important functionality, and none of the
-            ad hoc Buildroot-based systems, prevalent in the
-            embedded space, were scalable or maintainable.
-        </para>
-
-        <para>
-            Some important original goals for BitBake were:
-            <itemizedlist>
-                <listitem><para>
-                    Handle cross-compilation.
-                    </para></listitem>
-                <listitem><para>
-                    Handle inter-package dependencies (build time on
-                    target architecture, build time on native
-                    architecture, and runtime).
-                    </para></listitem>
-                <listitem><para>
-                    Support running any number of tasks within a given
-                    package, including, but not limited to, fetching
-                    upstream sources, unpacking them, patching them,
-                    configuring them, and so forth.
-                    </para></listitem>
-                <listitem><para>
-                    Be Linux distribution agnostic for both build and
-                    target systems.
-                    </para></listitem>
-                <listitem><para>
-                    Be architecture agnostic.
-                    </para></listitem>
-                <listitem><para>
-                    Support multiple build and target operating systems
-                    (e.g. Cygwin, the BSDs, and so forth).
-                    </para></listitem>
-                <listitem><para>
-                    Be self-contained, rather than tightly
-                    integrated into the build machine's root
-                    filesystem.
-                    </para></listitem>
-                <listitem><para>
-                    Handle conditional metadata on the target architecture,
-                    operating system, distribution, and machine.
-                    </para></listitem>
-                <listitem><para>
-                    Be easy to use the tools to supply local metadata and packages
-                    against which to operate.
-                    </para></listitem>
-                <listitem><para>
-                    Be easy to use BitBake to collaborate between multiple
-                    projects for their builds.
-                    </para></listitem>
-                <listitem><para>
-                    Provide an inheritance mechanism to share
-                    common metadata between many packages.
-                    </para></listitem>
-            </itemizedlist>
-            Over time it became apparent that some further requirements
-            were necessary:
-            <itemizedlist>
-                <listitem><para>
-                    Handle variants of a base recipe (e.g. native, sdk,
-                    and multilib).
-                    </para></listitem>
-                <listitem><para>
-                    Split metadata into layers and allow layers
-                    to enhance or override other layers.
-                    </para></listitem>
-                <listitem><para>
-                    Allow representation of a given set of input variables
-                    to a task as a checksum.
-                    Based on that checksum, allow acceleration of builds
-                    with prebuilt components.
-                    </para></listitem>
-            </itemizedlist>
-            BitBake satisfies all the original requirements and many more
-            with extensions being made to the basic functionality to
-            reflect the additional requirements.
-            Flexibility and power have always been the priorities.
-            BitBake is highly extensible and supports embedded Python code and
-            execution of any arbitrary tasks.
-        </para>
-    </section>
-
-    <section id="Concepts">
-        <title>Concepts</title>
-
-        <para>
-            BitBake is a program written in the Python language.
-            At the highest level, BitBake interprets metadata, decides
-            what tasks are required to run, and executes those tasks.
-            Similar to GNU Make, BitBake controls how software is
-            built.
-            GNU Make achieves its control through "makefiles", while
-            BitBake uses "recipes".
-        </para>
-
-        <para>
-            BitBake extends the capabilities of a simple
-            tool like GNU Make by allowing for the definition of much more
-            complex tasks, such as assembling entire embedded Linux
-            distributions.
-        </para>
-
-        <para>
-            The remainder of this section introduces several concepts
-            that should be understood in order to better leverage
-            the power of BitBake.
-        </para>
-
-        <section id='recipes'>
-            <title>Recipes</title>
-
-            <para>
-                BitBake Recipes, which are denoted by the file extension
-                <filename>.bb</filename>, are the most basic metadata files.
-                These recipe files provide BitBake with the following:
-                <itemizedlist>
-                    <listitem><para>Descriptive information about the
-                        package (author, homepage, license, and so on)</para></listitem>
-                    <listitem><para>The version of the recipe</para></listitem>
-                    <listitem><para>Existing dependencies (both build
-                        and runtime dependencies)</para></listitem>
-                    <listitem><para>Where the source code resides and
-                        how to fetch it</para></listitem>
-                    <listitem><para>Whether the source code requires
-                        any patches, where to find them, and how to apply
-                        them</para></listitem>
-                    <listitem><para>How to configure and compile the
-                        source code</para></listitem>
-                    <listitem><para>How to assemble the generated artifacts into
-                        one or more installable packages</para></listitem>
-                    <listitem><para>Where on the target machine to install the
-                        package or packages created</para></listitem>
-                </itemizedlist>
-            </para>
-
-            <para>
-                Within the context of BitBake, or any project utilizing BitBake
-                as its build system, files with the <filename>.bb</filename>
-                extension are referred to as <firstterm>recipes</firstterm>.
-                <note>
-                    The term "package" is also commonly used to describe recipes.
-                    However, since the same word is used to describe packaged
-                    output from a project, it is best to maintain a single
-                    descriptive term - "recipes".
-                    Put another way, a single "recipe" file is quite capable
-                    of generating a number of related but separately installable
-                    "packages".
-                    In fact, that ability is fairly common.
-                </note>
-            </para>
-        </section>
-
-        <section id='configuration-files'>
-            <title>Configuration Files</title>
-
-            <para>
-                Configuration files, which are denoted by the
-                <filename>.conf</filename> extension, define
-                various configuration variables that govern the project's build
-                process.
-                These files fall into several areas that define
-                machine configuration, distribution configuration,
-                possible compiler tuning, general common
-                configuration, and user configuration.
-                The main configuration file is the sample
-                <filename>bitbake.conf</filename> file, which is
-                located within the BitBake source tree
-                <filename>conf</filename> directory.
-            </para>
-        </section>
-
-        <section id='classes'>
-            <title>Classes</title>
-
-            <para>
-                Class files, which are denoted by the
-                <filename>.bbclass</filename> extension, contain
-                information that is useful to share between metadata files.
-                The BitBake source tree currently comes with one class metadata file
-                called <filename>base.bbclass</filename>.
-                You can find this file in the
-                <filename>classes</filename> directory.
-                The <filename>base.bbclass</filename> class files is special since it
-                is always included automatically for all recipes
-                and classes.
-                This class contains definitions for standard basic tasks such
-                as fetching, unpacking, configuring (empty by default),
-                compiling (runs any Makefile present), installing (empty by
-                default) and packaging (empty by default).
-                These tasks are often overridden or extended by other classes
-                added during the project development process.
-            </para>
-        </section>
-
-        <section id='layers'>
-            <title>Layers</title>
-
-            <para>
-                Layers allow you to isolate different types of
-                customizations from each other.
-                While you might find it tempting to keep everything in one layer
-                when working on a single project, the more modular
-                your metadata, the easier it is to cope with future changes.
-            </para>
-
-            <para>
-                To illustrate how you can use layers to keep things modular,
-                consider customizations you might make to support a specific target machine.
-                These types of customizations typically reside in a special layer,
-                rather than a general layer, called a <firstterm>Board Support Package</firstterm> (BSP)
-                layer.
-                Furthermore, the machine customizations should be isolated from
-                recipes and metadata that support a new GUI environment, for
-                example.
-                This situation gives you a couple of layers: one for the machine
-                configurations and one for the GUI environment.
-                It is important to understand, however, that the BSP layer can still
-                make machine-specific additions to recipes within
-                the GUI environment layer without polluting the GUI layer itself
-                with those machine-specific changes.
-                You can accomplish this through a recipe that is a BitBake append
-                (<filename>.bbappend</filename>) file.
-            </para>
-        </section>
-
-        <section id='append-bbappend-files'>
-            <title>Append Files</title>
-
-            <para>
-                Append files, which are files that have the
-                <filename>.bbappend</filename> file extension, extend or
-                override information in an existing recipe file.
-            </para>
-
-            <para>
-                BitBake expects every append file to have a corresponding recipe file.
-                Furthermore, the append file and corresponding recipe file
-                must use the same root filename.
-                The filenames can differ only in the file type suffix used
-                (e.g. <filename>formfactor_0.0.bb</filename> and
-                <filename>formfactor_0.0.bbappend</filename>).
-            </para>
-
-            <para>
-                Information in append files extends or
-                overrides the information in the underlying,
-                similarly-named recipe files.
-            </para>
-
-            <para>
-                When you name an append file, you can use the
-                "<filename>%</filename>" wildcard character to allow for matching
-                recipe names.
-                For example, suppose you have an append file named
-                as follows:
-                <literallayout class='monospaced'>
-     busybox_1.21.%.bbappend
-                </literallayout>
-                That append file would match any <filename>busybox_1.21.</filename><replaceable>x</replaceable><filename>.bb</filename>
-                version of the recipe.
-                So, the append file would match the following recipe names:
-                <literallayout class='monospaced'>
-     busybox_1.21.1.bb
-     busybox_1.21.2.bb
-     busybox_1.21.3.bb
-                </literallayout>
-                <note><title>Important</title>
-                    The use of the "<filename>%</filename>" character
-                    is limited in that it only works directly in front of the
-                    <filename>.bbappend</filename> portion of the append file's
-                    name.
-                    You cannot use the wildcard character in any other
-                    location of the name.
-                </note>
-                If the <filename>busybox</filename> recipe was updated to
-                <filename>busybox_1.3.0.bb</filename>, the append name would not
-                match.
-                However, if you named the append file
-                <filename>busybox_1.%.bbappend</filename>, then you would have a match.
-            </para>
-
-            <para>
-                In the most general case, you could name the append file something as
-                simple as <filename>busybox_%.bbappend</filename> to be entirely
-                version independent.
-            </para>
-        </section>
-    </section>
-
-    <section id='obtaining-bitbake'>
-        <title>Obtaining BitBake</title>
-
-        <para>
-            You can obtain BitBake several different ways:
-            <itemizedlist>
-                <listitem><para><emphasis>Cloning BitBake:</emphasis>
-                    Using Git to clone the BitBake source code repository
-                    is the recommended method for obtaining BitBake.
-                    Cloning the repository makes it easy to get bug fixes
-                    and have access to stable branches and the master
-                    branch.
-                    Once you have cloned BitBake, you should use
-                    the latest stable
-                    branch for development since the master branch is for
-                    BitBake development and might contain less stable changes.
-                    </para>
-                    <para>You usually need a version of BitBake
-                    that matches the metadata you are using.
-                    The metadata is generally backwards compatible but
-                    not forward compatible.</para>
-                    <para>Here is an example that clones the BitBake repository:
-                    <literallayout class='monospaced'>
-     $ git clone git://git.openembedded.org/bitbake
-                    </literallayout>
-                    This command clones the BitBake Git repository into a
-                    directory called <filename>bitbake</filename>.
-                    Alternatively, you can
-                    designate a directory after the
-                    <filename>git clone</filename> command
-                    if you want to call the new directory something
-                    other than <filename>bitbake</filename>.
-                    Here is an example that names the directory
-                    <filename>bbdev</filename>:
-                    <literallayout class='monospaced'>
-     $ git clone git://git.openembedded.org/bitbake bbdev
-                    </literallayout></para></listitem>
-                <listitem><para><emphasis>Installation using your Distribution
-                    Package Management System:</emphasis>
-                    This method is not
-                    recommended because the BitBake version that is
-                    provided by your distribution, in most cases,
-                    is several
-                    releases behind a snapshot of the BitBake repository.
-                    </para></listitem>
-                <listitem><para><emphasis>Taking a snapshot of BitBake:</emphasis>
-                    Downloading a snapshot of BitBake from the
-                    source code repository gives you access to a known
-                    branch or release of BitBake.
-                    <note>
-                         Cloning the Git repository, as described earlier,
-                         is the preferred method for getting BitBake.
-                         Cloning the repository makes it easier to update as
-                         patches are added to the stable branches.
-                    </note></para>
-                    <para>The following example downloads a snapshot of
-                    BitBake version 1.17.0:
-                    <literallayout class='monospaced'>
-     $ wget http://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
-     $ tar zxpvf bitbake-1.17.0.tar.gz
-                    </literallayout>
-                    After extraction of the tarball using the tar utility,
-                    you have a directory entitled
-                    <filename>bitbake-1.17.0</filename>.
-                    </para></listitem>
-                <listitem><para><emphasis>Using the BitBake that Comes With Your
-                    Build Checkout:</emphasis>
-                    A final possibility for getting a copy of BitBake is that it
-                    already comes with your checkout of a larger BitBake-based build
-                    system, such as Poky.
-                    Rather than manually checking out individual layers and
-                    gluing them together yourself, you can check
-                    out an entire build system.
-                    The checkout will already include a version of BitBake that
-                    has been thoroughly tested for compatibility with the other
-                    components.
-                    For information on how to check out a particular BitBake-based
-                    build system, consult that build system's supporting documentation.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id="bitbake-user-manual-command">
-        <title>The BitBake Command</title>
-
-        <para>
-            The <filename>bitbake</filename> command is the primary interface
-            to the BitBake tool.
-            This section presents the BitBake command syntax and provides
-            several execution examples.
-        </para>
-
-        <section id='usage-and-syntax'>
-            <title>Usage and syntax</title>
-
-            <para>
-                Following is the usage and syntax for BitBake:
-                <literallayout class='monospaced'>
-     $ bitbake -h
-     Usage: bitbake [options] [recipename/target recipe:do_task ...]
-
-         Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
-         It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
-         will provide the layer, BBFILES and other configuration information.
-
-     Options:
-       --version             show program's version number and exit
-       -h, --help            show this help message and exit
-       -b BUILDFILE, --buildfile=BUILDFILE
-                             Execute tasks from a specific .bb recipe directly.
-                             WARNING: Does not handle any dependencies from other
-                             recipes.
-       -k, --continue        Continue as much as possible after an error. While the
-                             target that failed and anything depending on it cannot
-                             be built, as much as possible will be built before
-                             stopping.
-       -f, --force           Force the specified targets/task to run (invalidating
-                             any existing stamp file).
-       -c CMD, --cmd=CMD     Specify the task to execute. The exact options
-                             available depend on the metadata. Some examples might
-                             be 'compile' or 'populate_sysroot' or 'listtasks' may
-                             give a list of the tasks available.
-       -C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
-                             Invalidate the stamp for the specified task such as
-                             'compile' and then run the default task for the
-                             specified target(s).
-       -r PREFILE, --read=PREFILE
-                             Read the specified file before bitbake.conf.
-       -R POSTFILE, --postread=POSTFILE
-                             Read the specified file after bitbake.conf.
-       -v, --verbose         Enable tracing of shell tasks (with 'set -x'). Also
-                             print bb.note(...) messages to stdout (in addition to
-                             writing them to ${T}/log.do_&lt;task&gt;).
-       -D, --debug           Increase the debug level. You can specify this more
-                             than once. -D sets the debug level to 1, where only
-                             bb.debug(1, ...) messages are printed to stdout; -DD
-                             sets the debug level to 2, where both bb.debug(1, ...)
-                             and bb.debug(2, ...) messages are printed; etc.
-                             Without -D, no debug messages are printed. Note that
-                             -D only affects output to stdout. All debug messages
-                             are written to ${T}/log.do_taskname, regardless of the
-                             debug level.
-       -q, --quiet           Output less log message data to the terminal. You can
-                             specify this more than once.
-       -n, --dry-run         Don't execute, just go through the motions.
-       -S SIGNATURE_HANDLER, --dump-signatures=SIGNATURE_HANDLER
-                             Dump out the signature construction information, with
-                             no task execution. The SIGNATURE_HANDLER parameter is
-                             passed to the handler. Two common values are none and
-                             printdiff but the handler may define more/less. none
-                             means only dump the signature, printdiff means compare
-                             the dumped signature with the cached one.
-       -p, --parse-only      Quit after parsing the BB recipes.
-       -s, --show-versions   Show current and preferred versions of all recipes.
-       -e, --environment     Show the global or per-recipe environment complete
-                             with information about where variables were
-                             set/changed.
-       -g, --graphviz        Save dependency tree information for the specified
-                             targets in the dot syntax.
-       -I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
-                             Assume these dependencies don't exist and are already
-                             provided (equivalent to ASSUME_PROVIDED). Useful to
-                             make dependency graphs more appealing
-       -l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
-                             Show debug logging for the specified logging domains
-       -P, --profile         Profile the command and save reports.
-       -u UI, --ui=UI        The user interface to use (knotty, ncurses or taskexp
-                             - default knotty).
-       --token=XMLRPCTOKEN   Specify the connection token to be used when
-                             connecting to a remote server.
-       --revisions-changed   Set the exit code depending on whether upstream
-                             floating revisions have changed or not.
-       --server-only         Run bitbake without a UI, only starting a server
-                             (cooker) process.
-       -B BIND, --bind=BIND  The name/address for the bitbake xmlrpc server to bind
-                             to.
-       -T SERVER_TIMEOUT, --idle-timeout=SERVER_TIMEOUT
-                             Set timeout to unload bitbake server due to
-                             inactivity, set to -1 means no unload, default:
-                             Environment variable BB_SERVER_TIMEOUT.
-       --no-setscene         Do not run any setscene tasks. sstate will be ignored
-                             and everything needed, built.
-       --setscene-only       Only run setscene tasks, don't run any real tasks.
-       --remote-server=REMOTE_SERVER
-                             Connect to the specified server.
-       -m, --kill-server     Terminate any running bitbake server.
-       --observe-only        Connect to a server as an observing-only client.
-       --status-only         Check the status of the remote bitbake server.
-       -w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
-                             Writes the event log of the build to a bitbake event
-                             json file. Use '' (empty string) to assign the name
-                             automatically.
-       --runall=RUNALL       Run the specified task for any recipe in the taskgraph
-                             of the specified target (even if it wouldn't otherwise
-                             have run).
-       --runonly=RUNONLY     Run only the specified task within the taskgraph of
-                             the specified targets (and any task dependencies those
-                             tasks may have).
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='bitbake-examples'>
-            <title>Examples</title>
-
-            <para>
-                This section presents some examples showing how to use BitBake.
-            </para>
-
-            <section id='example-executing-a-task-against-a-single-recipe'>
-                <title>Executing a Task Against a Single Recipe</title>
-
-                <para>
-                    Executing tasks for a single recipe file is relatively simple.
-                    You specify the file in question, and BitBake parses
-                    it and executes the specified task.
-                    If you do not specify a task, BitBake executes the default
-                    task, which is "build”.
-                    BitBake obeys inter-task dependencies when doing
-                    so.
-                </para>
-
-                <para>
-                    The following command runs the build task, which is
-                    the default task, on the <filename>foo_1.0.bb</filename>
-                    recipe file:
-                    <literallayout class='monospaced'>
-     $ bitbake -b foo_1.0.bb
-                    </literallayout>
-                    The following command runs the clean task on the
-                    <filename>foo.bb</filename> recipe file:
-                    <literallayout class='monospaced'>
-     $ bitbake -b foo.bb -c clean
-                    </literallayout>
-                    <note>
-                        The "-b" option explicitly does not handle recipe
-                        dependencies.
-                        Other than for debugging purposes, it is instead
-                        recommended that you use the syntax presented in the
-                        next section.
-                    </note>
-                </para>
-            </section>
-
-            <section id='executing-tasks-against-a-set-of-recipe-files'>
-                <title>Executing Tasks Against a Set of Recipe Files</title>
-
-                <para>
-                    There are a number of additional complexities introduced
-                    when one wants to manage multiple <filename>.bb</filename>
-                    files.
-                    Clearly there needs to be a way to tell BitBake what
-                    files are available and, of those, which you
-                    want to execute.
-                    There also needs to be a way for each recipe
-                    to express its dependencies, both for build-time and
-                    runtime.
-                    There must be a way for you to express recipe preferences
-                    when multiple recipes provide the same functionality, or when
-                    there are multiple versions of a recipe.
-                </para>
-
-                <para>
-                    The <filename>bitbake</filename> command, when not using
-                    "--buildfile" or "-b" only accepts a "PROVIDES".
-                    You cannot provide anything else.
-                    By default, a recipe file generally "PROVIDES" its
-                    "packagename" as shown in the following example:
-                    <literallayout class='monospaced'>
-     $ bitbake foo
-                    </literallayout>
-                    This next example "PROVIDES" the package name and also uses
-                    the "-c" option to tell BitBake to just execute the
-                    <filename>do_clean</filename> task:
-                    <literallayout class='monospaced'>
-     $ bitbake -c clean foo
-                    </literallayout>
-                </para>
-            </section>
-
-            <section id='executing-a-list-of-task-and-recipe-combinations'>
-                <title>Executing a List of Task and Recipe Combinations</title>
-
-                <para>
-                    The BitBake command line supports specifying different
-                    tasks for individual targets when you specify multiple
-                    targets.
-                    For example, suppose you had two targets (or recipes)
-                    <filename>myfirstrecipe</filename> and
-                    <filename>mysecondrecipe</filename> and you needed
-                    BitBake to run <filename>taskA</filename> for the first
-                    recipe and <filename>taskB</filename> for the second
-                    recipe:
-                    <literallayout class='monospaced'>
-     $ bitbake myfirstrecipe:do_taskA mysecondrecipe:do_taskB
-                    </literallayout>
-                </para>
-            </section>
-
-            <section id='generating-dependency-graphs'>
-                <title>Generating Dependency Graphs</title>
-
-                <para>
-                    BitBake is able to generate dependency graphs using
-                    the <filename>dot</filename> syntax.
-                    You can convert these graphs into images using the
-                    <filename>dot</filename> tool from
-                    <ulink url='http://www.graphviz.org'>Graphviz</ulink>.
-                </para>
-
-                <para>
-                    When you generate a dependency graph, BitBake writes two files
-                    to the current working directory:
-                    <itemizedlist>
-                        <listitem><para>
-                            <emphasis><filename>task-depends.dot</filename>:</emphasis>
-                            Shows dependencies between tasks.
-                            These dependencies match BitBake's internal task execution list.
-                            </para></listitem>
-                        <listitem><para>
-                            <emphasis><filename>pn-buildlist</filename>:</emphasis>
-                            Shows a simple list of targets that are to be built.
-                            </para></listitem>
-                    </itemizedlist>
-                </para>
-
-                <para>
-                    To stop depending on common depends, use the "-I" depend
-                    option and BitBake omits them from the graph.
-                    Leaving this information out can produce more readable graphs.
-                    This way, you can remove from the graph
-                    <filename>DEPENDS</filename> from inherited classes
-                    such as <filename>base.bbclass</filename>.
-                </para>
-
-                <para>
-                    Here are two examples that create dependency graphs.
-                    The second example omits depends common in OpenEmbedded from
-                    the graph:
-                    <literallayout class='monospaced'>
-     $ bitbake -g foo
-
-     $ bitbake -g -I virtual/kernel -I eglibc foo
-                    </literallayout>
-                </para>
-            </section>
-
-            <section id='executing-a-multiple-configuration-build'>
-                <title>Executing a Multiple Configuration Build</title>
-
-                <para>
-                    BitBake is able to build multiple images or packages
-                    using a single command where the different targets
-                    require different configurations (multiple configuration
-                    builds).
-                    Each target, in this scenario, is referred to as a
-                    "multiconfig".
-                </para>
-
-                <para>
-                    To accomplish a multiple configuration build, you must
-                    define each target's configuration separately using
-                    a parallel configuration file in the build directory.
-                    The location for these multiconfig configuration files
-                    is specific.
-                    They must reside in the current build directory in
-                    a sub-directory of <filename>conf</filename> named
-                    <filename>multiconfig</filename>.
-                    Following is an example for two separate targets:
-                    <imagedata fileref="figures/bb_multiconfig_files.png" align="center" width="4in" depth="3in" />
-                </para>
-
-                <para>
-                    The reason for this required file hierarchy
-                    is because the <filename>BBPATH</filename> variable
-                    is not constructed until the layers are parsed.
-                    Consequently, using the configuration file as a
-                    pre-configuration file is not possible unless it is
-                    located in the current working directory.
-                </para>
-
-                <para>
-                    Minimally, each configuration file must define the
-                    machine and the temporary directory BitBake uses
-                    for the build.
-                    Suggested practice dictates that you do not
-                    overlap the temporary directories used during the
-                    builds.
-                </para>
-
-                <para>
-                    Aside from separate configuration files for each
-                    target, you must also enable BitBake to perform multiple
-                    configuration builds.
-                    Enabling is accomplished by setting the
-                    <link linkend='var-bb-BBMULTICONFIG'><filename>BBMULTICONFIG</filename></link>
-                    variable in the <filename>local.conf</filename>
-                    configuration file.
-                    As an example, suppose you had configuration files
-                    for <filename>target1</filename> and
-                    <filename>target2</filename> defined in the build
-                    directory.
-                    The following statement in the
-                    <filename>local.conf</filename> file both enables
-                    BitBake to perform multiple configuration builds and
-                    specifies the two extra multiconfigs:
-                    <literallayout class='monospaced'>
-     BBMULTICONFIG = "target1 target2"
-                    </literallayout>
-                </para>
-
-                <para>
-                    Once the target configuration files are in place and
-                    BitBake has been enabled to perform multiple configuration
-                    builds, use the following command form to start the
-                    builds:
-                    <literallayout class='monospaced'>
-     $ bitbake [mc:<replaceable>multiconfigname</replaceable>:]<replaceable>target</replaceable> [[[mc:<replaceable>multiconfigname</replaceable>:]<replaceable>target</replaceable>] ... ]
-                    </literallayout>
-                    Here is an example for two extra multiconfigs:
-                    <filename>target1</filename> and
-                    <filename>target2</filename>:
-                    <literallayout class='monospaced'>
-     $ bitbake mc::<replaceable>target</replaceable> mc:target1:<replaceable>target</replaceable> mc:target2:<replaceable>target</replaceable>
-                    </literallayout>
-                </para>
-            </section>
-
-            <section id='bb-enabling-multiple-configuration-build-dependencies'>
-                <title>Enabling Multiple Configuration Build Dependencies</title>
-
-                <para>
-                    Sometimes dependencies can exist between targets
-                    (multiconfigs) in a multiple configuration build.
-                    For example, suppose that in order to build an image
-                    for a particular architecture, the root filesystem of
-                    another build for a different architecture needs to
-                    exist.
-                    In other words, the image for the first multiconfig depends
-                    on the root filesystem of the second multiconfig.
-                    This dependency is essentially that the task in the recipe
-                    that builds one multiconfig is dependent on the
-                    completion of the task in the recipe that builds
-                    another multiconfig.
-                </para>
-
-                <para>
-                    To enable dependencies in a multiple configuration
-                    build, you must declare the dependencies in the recipe
-                    using the following statement form:
-                    <literallayout class='monospaced'>
-     <replaceable>task_or_package</replaceable>[mcdepends] = "mc:<replaceable>from_multiconfig</replaceable>:<replaceable>to_multiconfig</replaceable>:<replaceable>recipe_name</replaceable>:<replaceable>task_on_which_to_depend</replaceable>"
-                    </literallayout>
-                    To better show how to use this statement, consider an
-                    example with two multiconfigs: <filename>target1</filename>
-                    and <filename>target2</filename>:
-                    <literallayout class='monospaced'>
-     <replaceable>image_task</replaceable>[mcdepends] = "mc:target1:target2:<replaceable>image2</replaceable>:<replaceable>rootfs_task</replaceable>"
-                    </literallayout>
-                    In this example, the
-                    <replaceable>from_multiconfig</replaceable> is "target1" and
-                    the <replaceable>to_multiconfig</replaceable> is "target2".
-                    The task on which the image whose recipe contains
-                    <replaceable>image_task</replaceable> depends on the
-                    completion of the <replaceable>rootfs_task</replaceable>
-                    used to build out <replaceable>image2</replaceable>, which
-                    is associated with the "target2" multiconfig.
-               </para>
-
-               <para>
-                   Once you set up this dependency, you can build the
-                   "target1" multiconfig using a BitBake command as follows:
-                   <literallayout class='monospaced'>
-     $ bitbake mc:target1:<replaceable>image1</replaceable>
-                   </literallayout>
-                   This command executes all the tasks needed to create
-                   <replaceable>image1</replaceable> for the "target1"
-                   multiconfig.
-                   Because of the dependency, BitBake also executes through
-                   the <replaceable>rootfs_task</replaceable> for the "target2"
-                   multiconfig build.
-               </para>
-
-               <para>
-                   Having a recipe depend on the root filesystem of another
-                   build might not seem that useful.
-                   Consider this change to the statement in the
-                   <replaceable>image1</replaceable> recipe:
-                   <literallayout class='monospaced'>
-     <replaceable>image_task</replaceable>[mcdepends] = "mc:target1:target2:<replaceable>image2</replaceable>:<replaceable>image_task</replaceable>"
-                   </literallayout>
-                   In this case, BitBake must create
-                   <replaceable>image2</replaceable> for the "target2"
-                   build since the "target1" build depends on it.
-               </para>
-
-               <para>
-                   Because "target1" and "target2" are enabled for multiple
-                   configuration builds and have separate configuration
-                   files, BitBake places the artifacts for each build in the
-                   respective temporary build directories.
-               </para>
-            </section>
-        </section>
-    </section>
-</chapter>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.rst
new file mode 100644
index 00000000..d4190c26
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.rst
@@ -0,0 +1,1980 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+====================
+Syntax and Operators
+====================
+
+|
+
+BitBake files have their own syntax. The syntax has similarities to
+several other languages but also has some unique features. This section
+describes the available syntax and operators as well as provides
+examples.
+
+Basic Syntax
+============
+
+This section provides some basic syntax examples.
+
+Basic Variable Setting
+----------------------
+
+The following example sets ``VARIABLE`` to "value". This assignment
+occurs immediately as the statement is parsed. It is a "hard"
+assignment. ::
+
+   VARIABLE = "value"
+
+As expected, if you include leading or
+trailing spaces as part of an assignment, the spaces are retained: ::
+
+   VARIABLE = " value"
+   VARIABLE = "value "
+
+Setting ``VARIABLE`` to "" sets
+it to an empty string, while setting the variable to " " sets it to a
+blank space (i.e. these are not the same values). ::
+
+   VARIABLE = ""
+   VARIABLE = " "
+
+You can use single quotes instead of double quotes when setting a
+variable's value. Doing so allows you to use values that contain the
+double quote character: ::
+
+   VARIABLE = 'I have a " in my value'
+
+.. note::
+
+   Unlike in Bourne shells, single quotes work identically to double
+   quotes in all other ways. They do not suppress variable expansions.
+
+Modifying Existing Variables
+----------------------------
+
+Sometimes you need to modify existing variables. Following are some
+cases where you might find you want to modify an existing variable:
+
+-  Customize a recipe that uses the variable.
+
+-  Change a variable's default value used in a ``*.bbclass`` file.
+
+-  Change the variable in a ``*.bbappend`` file to override the variable
+   in the original recipe.
+
+-  Change the variable in a configuration file so that the value
+   overrides an existing configuration.
+
+Changing a variable value can sometimes depend on how the value was
+originally assigned and also on the desired intent of the change. In
+particular, when you append a value to a variable that has a default
+value, the resulting value might not be what you expect. In this case,
+the value you provide might replace the value rather than append to the
+default value.
+
+If after you have changed a variable's value and something unexplained
+occurs, you can use BitBake to check the actual value of the suspect
+variable. You can make these checks for both configuration and recipe
+level changes:
+
+-  For configuration changes, use the following: ::
+
+      $ bitbake -e
+
+   This
+   command displays variable values after the configuration files (i.e.
+   ``local.conf``, ``bblayers.conf``, ``bitbake.conf`` and so forth)
+   have been parsed.
+
+   .. note::
+
+      Variables that are exported to the environment are preceded by the
+      string "export" in the command's output.
+
+-  For recipe changes, use the following: ::
+
+      $ bitbake recipe -e \| grep VARIABLE="
+
+   This command checks to see if the variable actually makes
+   it into a specific recipe.
+
+Line Joining
+------------
+
+Outside of :ref:`functions <bitbake-user-manual/bitbake-user-manual-metadata:functions>`,
+BitBake joins any line ending in
+a backslash character ("\") with the following line before parsing
+statements. The most common use for the "\" character is to split
+variable assignments over multiple lines, as in the following example: ::
+
+   FOO = "bar \
+          baz \
+          qaz"
+
+Both the "\" character and the newline
+character that follow it are removed when joining lines. Thus, no
+newline characters end up in the value of ``FOO``.
+
+Consider this additional example where the two assignments both assign
+"barbaz" to ``FOO``: ::
+
+   FOO = "barbaz"
+   FOO = "bar\
+   baz"
+
+.. note::
+
+   BitBake does not interpret escape sequences like "\n" in variable
+   values. For these to have an effect, the value must be passed to some
+   utility that interprets escape sequences, such as
+   ``printf`` or ``echo -n``.
+
+Variable Expansion
+------------------
+
+Variables can reference the contents of other variables using a syntax
+that is similar to variable expansion in Bourne shells. The following
+assignments result in A containing "aval" and B evaluating to
+"preavalpost". ::
+
+   A = "aval"
+   B = "pre${A}post"
+
+.. note::
+
+   Unlike in Bourne shells, the curly braces are mandatory: Only ``${FOO}`` and not
+   ``$FOO`` is recognized as an expansion of ``FOO``.
+
+The "=" operator does not immediately expand variable references in the
+right-hand side. Instead, expansion is deferred until the variable
+assigned to is actually used. The result depends on the current values
+of the referenced variables. The following example should clarify this
+behavior: ::
+
+   A = "${B} baz"
+   B = "${C} bar"
+   C = "foo"
+   *At this point, ${A} equals "foo bar baz"*
+   C = "qux"
+   *At this point, ${A} equals "qux bar baz"*
+   B = "norf"
+   *At this point, ${A} equals "norf baz"\*
+
+Contrast this behavior with the
+:ref:`bitbake-user-manual/bitbake-user-manual-metadata:immediate variable
+expansion (:=)` operator.
+
+If the variable expansion syntax is used on a variable that does not
+exist, the string is kept as is. For example, given the following
+assignment, ``BAR`` expands to the literal string "${FOO}" as long as
+``FOO`` does not exist. ::
+
+   BAR = "${FOO}"
+
+Setting a default value (?=)
+----------------------------
+
+You can use the "?=" operator to achieve a "softer" assignment for a
+variable. This type of assignment allows you to define a variable if it
+is undefined when the statement is parsed, but to leave the value alone
+if the variable has a value. Here is an example: ::
+
+   A ?= "aval"
+
+If ``A`` is
+set at the time this statement is parsed, the variable retains its
+value. However, if ``A`` is not set, the variable is set to "aval".
+
+.. note::
+
+   This assignment is immediate. Consequently, if multiple "?="
+   assignments to a single variable exist, the first of those ends up
+   getting used.
+
+Setting a weak default value (??=)
+----------------------------------
+
+It is possible to use a "weaker" assignment than in the previous section
+by using the "??=" operator. This assignment behaves identical to "?="
+except that the assignment is made at the end of the parsing process
+rather than immediately. Consequently, when multiple "??=" assignments
+exist, the last one is used. Also, any "=" or "?=" assignment will
+override the value set with "??=". Here is an example: ::
+
+   A ??= "somevalue"
+   A ??= "someothervalue"
+
+If ``A`` is set before the above statements are
+parsed, the variable retains its value. If ``A`` is not set, the
+variable is set to "someothervalue".
+
+Again, this assignment is a "lazy" or "weak" assignment because it does
+not occur until the end of the parsing process.
+
+Immediate variable expansion (:=)
+---------------------------------
+
+The ":=" operator results in a variable's contents being expanded
+immediately, rather than when the variable is actually used: ::
+
+   T = "123"
+   A := "test ${T}"
+   T = "456"
+   B := "${T} ${C}"
+   C = "cval"
+   C := "${C}append"
+
+In this example, ``A`` contains "test 123", even though the final value
+of ``T`` is "456". The variable ``B`` will end up containing "456
+cvalappend". This is because references to undefined variables are
+preserved as is during (immediate)expansion. This is in contrast to GNU
+Make, where undefined variables expand to nothing. The variable ``C``
+contains "cvalappend" since ``${C}`` immediately expands to "cval".
+
+.. _appending-and-prepending:
+
+Appending (+=) and prepending (=+) With Spaces
+----------------------------------------------
+
+Appending and prepending values is common and can be accomplished using
+the "+=" and "=+" operators. These operators insert a space between the
+current value and prepended or appended value.
+
+These operators take immediate effect during parsing. Here are some
+examples: ::
+
+   B = "bval"
+   B += "additionaldata"
+   C = "cval"
+   C =+ "test"
+
+The variable ``B`` contains "bval additionaldata" and ``C`` contains "test
+cval".
+
+.. _appending-and-prepending-without-spaces:
+
+Appending (.=) and Prepending (=.) Without Spaces
+-------------------------------------------------
+
+If you want to append or prepend values without an inserted space, use
+the ".=" and "=." operators.
+
+These operators take immediate effect during parsing. Here are some
+examples: ::
+
+   B = "bval"
+   B .= "additionaldata"
+   C = "cval"
+   C =. "test"
+
+The variable ``B`` contains "bvaladditionaldata" and ``C`` contains
+"testcval".
+
+Appending and Prepending (Override Style Syntax)
+------------------------------------------------
+
+You can also append and prepend a variable's value using an override
+style syntax. When you use this syntax, no spaces are inserted.
+
+These operators differ from the ":=", ".=", "=.", "+=", and "=+"
+operators in that their effects are applied at variable expansion time
+rather than being immediately applied. Here are some examples: ::
+
+   B = "bval"
+   B_append = " additional data"
+   C = "cval"
+   C_prepend = "additional data "
+   D = "dval"
+   D_append = "additional data"
+
+The variable ``B``
+becomes "bval additional data" and ``C`` becomes "additional data cval".
+The variable ``D`` becomes "dvaladditional data".
+
+.. note::
+
+   You must control all spacing when you use the override syntax.
+
+It is also possible to append and prepend to shell functions and
+BitBake-style Python functions. See the ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:shell functions`" and ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:bitbake-style python functions`"
+sections for examples.
+
+.. _removing-override-style-syntax:
+
+Removal (Override Style Syntax)
+-------------------------------
+
+You can remove values from lists using the removal override style
+syntax. Specifying a value for removal causes all occurrences of that
+value to be removed from the variable.
+
+When you use this syntax, BitBake expects one or more strings.
+Surrounding spaces and spacing are preserved. Here is an example: ::
+
+   FOO = "123 456 789 123456 123 456 123 456"
+   FOO_remove = "123"
+   FOO_remove = "456"
+   FOO2 = " abc def ghi abcdef abc def abc def def"
+   FOO2_remove = "\
+       def \
+       abc \
+       ghi \
+       "
+
+The variable ``FOO`` becomes
+"  789 123456    " and ``FOO2`` becomes "    abcdef     ".
+
+Like "_append" and "_prepend", "_remove" is applied at variable
+expansion time.
+
+Override Style Operation Advantages
+-----------------------------------
+
+An advantage of the override style operations "_append", "_prepend", and
+"_remove" as compared to the "+=" and "=+" operators is that the
+override style operators provide guaranteed operations. For example,
+consider a class ``foo.bbclass`` that needs to add the value "val" to
+the variable ``FOO``, and a recipe that uses ``foo.bbclass`` as follows: ::
+
+   inherit foo
+   FOO = "initial"
+
+If ``foo.bbclass`` uses the "+=" operator,
+as follows, then the final value of ``FOO`` will be "initial", which is
+not what is desired: ::
+
+   FOO += "val"
+
+If, on the other hand, ``foo.bbclass``
+uses the "_append" operator, then the final value of ``FOO`` will be
+"initial val", as intended: ::
+
+   FOO_append = " val"
+
+.. note::
+
+   It is never necessary to use "+=" together with "_append". The following
+   sequence of assignments appends "barbaz" to FOO: ::
+
+       FOO_append = "bar"
+       FOO_append = "baz"
+
+
+   The only effect of changing the second assignment in the previous
+   example to use "+=" would be to add a space before "baz" in the
+   appended value (due to how the "+=" operator works).
+
+Another advantage of the override style operations is that you can
+combine them with other overrides as described in the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:conditional syntax (overrides)`" section.
+
+Variable Flag Syntax
+--------------------
+
+Variable flags are BitBake's implementation of variable properties or
+attributes. It is a way of tagging extra information onto a variable.
+You can find more out about variable flags in general in the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:variable flags`" section.
+
+You can define, append, and prepend values to variable flags. All the
+standard syntax operations previously mentioned work for variable flags
+except for override style syntax (i.e. "_prepend", "_append", and
+"_remove").
+
+Here are some examples showing how to set variable flags: ::
+
+   FOO[a] = "abc"
+   FOO[b] = "123"
+   FOO[a] += "456"
+
+The variable ``FOO`` has two flags:
+``[a]`` and ``[b]``. The flags are immediately set to "abc" and "123",
+respectively. The ``[a]`` flag becomes "abc 456".
+
+No need exists to pre-define variable flags. You can simply start using
+them. One extremely common application is to attach some brief
+documentation to a BitBake variable as follows: ::
+
+   CACHE[doc] = "The directory holding the cache of the metadata."
+
+Inline Python Variable Expansion
+--------------------------------
+
+You can use inline Python variable expansion to set variables. Here is
+an example: ::
+
+   DATE = "${@time.strftime('%Y%m%d',time.gmtime())}"
+
+This example results in the ``DATE`` variable being set to the current date.
+
+Probably the most common use of this feature is to extract the value of
+variables from BitBake's internal data dictionary, ``d``. The following
+lines select the values of a package name and its version number,
+respectively: ::
+
+   PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
+   PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
+
+.. note::
+
+   Inline Python expressions work just like variable expansions insofar as the
+   "=" and ":=" operators are concerned. Given the following assignment, foo()
+   is called each time FOO is expanded: ::
+
+      FOO = "${@foo()}"
+
+   Contrast this with the following immediate assignment, where foo() is only
+   called once, while the assignment is parsed: ::
+
+      FOO := "${@foo()}"
+
+For a different way to set variables with Python code during parsing,
+see the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:anonymous python functions`" section.
+
+Unsetting variables
+-------------------
+
+It is possible to completely remove a variable or a variable flag from
+BitBake's internal data dictionary by using the "unset" keyword. Here is
+an example: ::
+
+   unset DATE
+   unset do_fetch[noexec]
+
+These two statements remove the ``DATE`` and the ``do_fetch[noexec]`` flag.
+
+Providing Pathnames
+-------------------
+
+When specifying pathnames for use with BitBake, do not use the tilde
+("~") character as a shortcut for your home directory. Doing so might
+cause BitBake to not recognize the path since BitBake does not expand
+this character in the same way a shell would.
+
+Instead, provide a fuller path as the following example illustrates: ::
+
+   BBLAYERS ?= " \
+       /home/scott-lenovo/LayerA \
+   "
+
+Exporting Variables to the Environment
+======================================
+
+You can export variables to the environment of running tasks by using
+the ``export`` keyword. For example, in the following example, the
+``do_foo`` task prints "value from the environment" when run: ::
+
+   export ENV_VARIABLE
+   ENV_VARIABLE = "value from the environment"
+
+   do_foo() {
+       bbplain "$ENV_VARIABLE"
+   }
+
+.. note::
+
+   BitBake does not expand ``$ENV_VARIABLE`` in this case because it lacks the
+   obligatory ``{}`` . Rather, ``$ENV_VARIABLE`` is expanded by the shell.
+
+It does not matter whether ``export ENV_VARIABLE`` appears before or
+after assignments to ``ENV_VARIABLE``.
+
+It is also possible to combine ``export`` with setting a value for the
+variable. Here is an example: ::
+
+   export ENV_VARIABLE = "variable-value"
+
+In the output of ``bitbake -e``, variables that are exported to the
+environment are preceded by "export".
+
+Among the variables commonly exported to the environment are ``CC`` and
+``CFLAGS``, which are picked up by many build systems.
+
+Conditional Syntax (Overrides)
+==============================
+
+BitBake uses :term:`OVERRIDES` to control what
+variables are overridden after BitBake parses recipes and configuration
+files. This section describes how you can use ``OVERRIDES`` as
+conditional metadata, talks about key expansion in relationship to
+``OVERRIDES``, and provides some examples to help with understanding.
+
+Conditional Metadata
+--------------------
+
+You can use ``OVERRIDES`` to conditionally select a specific version of
+a variable and to conditionally append or prepend the value of a
+variable.
+
+.. note::
+
+   Overrides can only use lower-case characters. Additionally,
+   underscores are not permitted in override names as they are used to
+   separate overrides from each other and from the variable name.
+
+-  *Selecting a Variable:* The ``OVERRIDES`` variable is a
+   colon-character-separated list that contains items for which you want
+   to satisfy conditions. Thus, if you have a variable that is
+   conditional on "arm", and "arm" is in ``OVERRIDES``, then the
+   "arm"-specific version of the variable is used rather than the
+   non-conditional version. Here is an example: ::
+
+      OVERRIDES = "architecture:os:machine"
+      TEST = "default"
+      TEST_os = "osspecific"
+      TEST_nooverride = "othercondvalue"
+
+   In this example, the ``OVERRIDES``
+   variable lists three overrides: "architecture", "os", and "machine".
+   The variable ``TEST`` by itself has a default value of "default". You
+   select the os-specific version of the ``TEST`` variable by appending
+   the "os" override to the variable (i.e. ``TEST_os``).
+
+   To better understand this, consider a practical example that assumes
+   an OpenEmbedded metadata-based Linux kernel recipe file. The
+   following lines from the recipe file first set the kernel branch
+   variable ``KBRANCH`` to a default value, then conditionally override
+   that value based on the architecture of the build: ::
+
+      KBRANCH = "standard/base"
+      KBRANCH_qemuarm = "standard/arm-versatile-926ejs"
+      KBRANCH_qemumips = "standard/mti-malta32"
+      KBRANCH_qemuppc = "standard/qemuppc"
+      KBRANCH_qemux86 = "standard/common-pc/base"
+      KBRANCH_qemux86-64 = "standard/common-pc-64/base"
+      KBRANCH_qemumips64 = "standard/mti-malta64"
+
+-  *Appending and Prepending:* BitBake also supports append and prepend
+   operations to variable values based on whether a specific item is
+   listed in ``OVERRIDES``. Here is an example: ::
+
+      DEPENDS = "glibc ncurses"
+      OVERRIDES = "machine:local"
+      DEPENDS_append_machine = "libmad"
+
+   In this example, ``DEPENDS`` becomes "glibc ncurses libmad".
+
+   Again, using an OpenEmbedded metadata-based kernel recipe file as an
+   example, the following lines will conditionally append to the
+   ``KERNEL_FEATURES`` variable based on the architecture: ::
+
+      KERNEL_FEATURES_append = " ${KERNEL_EXTRA_FEATURES}"
+      KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc"
+      KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc"
+
+-  *Setting a Variable for a Single Task:* BitBake supports setting a
+   variable just for the duration of a single task. Here is an example: ::
+
+      FOO_task-configure = "val 1"
+      FOO_task-compile = "val 2"
+
+   In the
+   previous example, ``FOO`` has the value "val 1" while the
+   ``do_configure`` task is executed, and the value "val 2" while the
+   ``do_compile`` task is executed.
+
+   Internally, this is implemented by prepending the task (e.g.
+   "task-compile:") to the value of
+   :term:`OVERRIDES` for the local datastore of the
+   ``do_compile`` task.
+
+   You can also use this syntax with other combinations (e.g.
+   "``_prepend``") as shown in the following example: ::
+
+      EXTRA_OEMAKE_prepend_task-compile = "${PARALLEL_MAKE} "
+
+Key Expansion
+-------------
+
+Key expansion happens when the BitBake datastore is finalized. To better
+understand this, consider the following example: ::
+
+   A${B} = "X"
+   B = "2"
+   A2 = "Y"
+
+In this case, after all the parsing is complete, BitBake expands
+``${B}`` into "2". This expansion causes ``A2``, which was set to "Y"
+before the expansion, to become "X".
+
+.. _variable-interaction-worked-examples:
+
+Examples
+--------
+
+Despite the previous explanations that show the different forms of
+variable definitions, it can be hard to work out exactly what happens
+when variable operators, conditional overrides, and unconditional
+overrides are combined. This section presents some common scenarios
+along with explanations for variable interactions that typically confuse
+users.
+
+There is often confusion concerning the order in which overrides and
+various "append" operators take effect. Recall that an append or prepend
+operation using "_append" and "_prepend" does not result in an immediate
+assignment as would "+=", ".=", "=+", or "=.". Consider the following
+example: ::
+
+   OVERRIDES = "foo"
+   A = "Z"
+   A_foo_append = "X"
+
+For this case,
+``A`` is unconditionally set to "Z" and "X" is unconditionally and
+immediately appended to the variable ``A_foo``. Because overrides have
+not been applied yet, ``A_foo`` is set to "X" due to the append and
+``A`` simply equals "Z".
+
+Applying overrides, however, changes things. Since "foo" is listed in
+``OVERRIDES``, the conditional variable ``A`` is replaced with the "foo"
+version, which is equal to "X". So effectively, ``A_foo`` replaces
+``A``.
+
+This next example changes the order of the override and the append: ::
+
+   OVERRIDES = "foo"
+   A = "Z"
+   A_append_foo = "X"
+
+For this case, before
+overrides are handled, ``A`` is set to "Z" and ``A_append_foo`` is set
+to "X". Once the override for "foo" is applied, however, ``A`` gets
+appended with "X". Consequently, ``A`` becomes "ZX". Notice that spaces
+are not appended.
+
+This next example has the order of the appends and overrides reversed
+back as in the first example: ::
+
+   OVERRIDES = "foo"
+   A = "Y"
+   A_foo_append = "Z"
+   A_foo_append = "X"
+
+For this case, before any overrides are resolved,
+``A`` is set to "Y" using an immediate assignment. After this immediate
+assignment, ``A_foo`` is set to "Z", and then further appended with "X"
+leaving the variable set to "ZX". Finally, applying the override for
+"foo" results in the conditional variable ``A`` becoming "ZX" (i.e.
+``A`` is replaced with ``A_foo``).
+
+This final example mixes in some varying operators: ::
+
+   A = "1"
+   A_append = "2"
+   A_append = "3"
+   A += "4"
+   A .= "5"
+
+For this case, the type of append
+operators are affecting the order of assignments as BitBake passes
+through the code multiple times. Initially, ``A`` is set to "1 45"
+because of the three statements that use immediate operators. After
+these assignments are made, BitBake applies the "_append" operations.
+Those operations result in ``A`` becoming "1 4523".
+
+Sharing Functionality
+=====================
+
+BitBake allows for metadata sharing through include files (``.inc``) and
+class files (``.bbclass``). For example, suppose you have a piece of
+common functionality such as a task definition that you want to share
+between more than one recipe. In this case, creating a ``.bbclass`` file
+that contains the common functionality and then using the ``inherit``
+directive in your recipes to inherit the class would be a common way to
+share the task.
+
+This section presents the mechanisms BitBake provides to allow you to
+share functionality between recipes. Specifically, the mechanisms
+include ``include``, ``inherit``, ``INHERIT``, and ``require``
+directives.
+
+Locating Include and Class Files
+--------------------------------
+
+BitBake uses the :term:`BBPATH` variable to locate
+needed include and class files. Additionally, BitBake searches the
+current directory for ``include`` and ``require`` directives.
+
+.. note::
+
+   The BBPATH variable is analogous to the environment variable PATH .
+
+In order for include and class files to be found by BitBake, they need
+to be located in a "classes" subdirectory that can be found in
+``BBPATH``.
+
+``inherit`` Directive
+---------------------
+
+When writing a recipe or class file, you can use the ``inherit``
+directive to inherit the functionality of a class (``.bbclass``).
+BitBake only supports this directive when used within recipe and class
+files (i.e. ``.bb`` and ``.bbclass``).
+
+The ``inherit`` directive is a rudimentary means of specifying
+functionality contained in class files that your recipes require. For
+example, you can easily abstract out the tasks involved in building a
+package that uses Autoconf and Automake and put those tasks into a class
+file and then have your recipe inherit that class file.
+
+As an example, your recipes could use the following directive to inherit
+an ``autotools.bbclass`` file. The class file would contain common
+functionality for using Autotools that could be shared across recipes: ::
+
+   inherit autotools
+
+In this case, BitBake would search for the directory
+``classes/autotools.bbclass`` in ``BBPATH``.
+
+.. note::
+
+   You can override any values and functions of the inherited class
+   within your recipe by doing so after the "inherit" statement.
+
+If you want to use the directive to inherit multiple classes, separate
+them with spaces. The following example shows how to inherit both the
+``buildhistory`` and ``rm_work`` classes: ::
+
+   inherit buildhistory rm_work
+
+An advantage with the inherit directive as compared to both the
+:ref:`include <bitbake-user-manual/bitbake-user-manual-metadata:\`\`include\`\` directive>` and :ref:`require <bitbake-user-manual/bitbake-user-manual-metadata:\`\`require\`\` directive>`
+directives is that you can inherit class files conditionally. You can
+accomplish this by using a variable expression after the ``inherit``
+statement. Here is an example: ::
+
+   inherit ${VARNAME}
+
+If ``VARNAME`` is
+going to be set, it needs to be set before the ``inherit`` statement is
+parsed. One way to achieve a conditional inherit in this case is to use
+overrides: ::
+
+   VARIABLE = ""
+   VARIABLE_someoverride = "myclass"
+
+Another method is by using anonymous Python. Here is an example: ::
+
+   python () {
+       if condition == value:
+           d.setVar('VARIABLE', 'myclass')
+       else:
+           d.setVar('VARIABLE', '')
+   }
+
+Alternatively, you could use an in-line Python expression in the
+following form: ::
+
+   inherit ${@'classname' if condition else ''}
+   inherit ${@functionname(params)}
+
+In all cases, if the expression evaluates to an
+empty string, the statement does not trigger a syntax error because it
+becomes a no-op.
+
+``include`` Directive
+---------------------
+
+BitBake understands the ``include`` directive. This directive causes
+BitBake to parse whatever file you specify, and to insert that file at
+that location. The directive is much like its equivalent in Make except
+that if the path specified on the include line is a relative path,
+BitBake locates the first file it can find within ``BBPATH``.
+
+The include directive is a more generic method of including
+functionality as compared to the :ref:`inherit <bitbake-user-manual/bitbake-user-manual-metadata:\`\`inherit\`\` directive>`
+directive, which is restricted to class (i.e. ``.bbclass``) files. The
+include directive is applicable for any other kind of shared or
+encapsulated functionality or configuration that does not suit a
+``.bbclass`` file.
+
+As an example, suppose you needed a recipe to include some self-test
+definitions: ::
+
+   include test_defs.inc
+
+.. note::
+
+   The include directive does not produce an error when the file cannot be
+   found.  Consequently, it is recommended that if the file you are including is
+   expected to exist, you should use :ref:`require <require-inclusion>` instead
+   of include . Doing so makes sure that an error is produced if the file cannot
+   be found.
+
+.. _require-inclusion:
+
+``require`` Directive
+---------------------
+
+BitBake understands the ``require`` directive. This directive behaves
+just like the ``include`` directive with the exception that BitBake
+raises a parsing error if the file to be included cannot be found. Thus,
+any file you require is inserted into the file that is being parsed at
+the location of the directive.
+
+The require directive, like the include directive previously described,
+is a more generic method of including functionality as compared to the
+:ref:`inherit <bitbake-user-manual/bitbake-user-manual-metadata:\`\`inherit\`\` directive>` directive, which is restricted to class
+(i.e. ``.bbclass``) files. The require directive is applicable for any
+other kind of shared or encapsulated functionality or configuration that
+does not suit a ``.bbclass`` file.
+
+Similar to how BitBake handles :ref:`include <bitbake-user-manual/bitbake-user-manual-metadata:\`\`include\`\` directive>`, if
+the path specified on the require line is a relative path, BitBake
+locates the first file it can find within ``BBPATH``.
+
+As an example, suppose you have two versions of a recipe (e.g.
+``foo_1.2.2.bb`` and ``foo_2.0.0.bb``) where each version contains some
+identical functionality that could be shared. You could create an
+include file named ``foo.inc`` that contains the common definitions
+needed to build "foo". You need to be sure ``foo.inc`` is located in the
+same directory as your two recipe files as well. Once these conditions
+are set up, you can share the functionality using a ``require``
+directive from within each recipe: ::
+
+   require foo.inc
+
+``INHERIT`` Configuration Directive
+-----------------------------------
+
+When creating a configuration file (``.conf``), you can use the
+:term:`INHERIT` configuration directive to inherit a
+class. BitBake only supports this directive when used within a
+configuration file.
+
+As an example, suppose you needed to inherit a class file called
+``abc.bbclass`` from a configuration file as follows: ::
+
+   INHERIT += "abc"
+
+This configuration directive causes the named class to be inherited at
+the point of the directive during parsing. As with the ``inherit``
+directive, the ``.bbclass`` file must be located in a "classes"
+subdirectory in one of the directories specified in ``BBPATH``.
+
+.. note::
+
+   Because .conf files are parsed first during BitBake's execution, using
+   INHERIT to inherit a class effectively inherits the class globally (i.e. for
+   all recipes).
+
+If you want to use the directive to inherit multiple classes, you can
+provide them on the same line in the ``local.conf`` file. Use spaces to
+separate the classes. The following example shows how to inherit both
+the ``autotools`` and ``pkgconfig`` classes: ::
+
+   INHERIT += "autotools pkgconfig"
+
+Functions
+=========
+
+As with most languages, functions are the building blocks that are used
+to build up operations into tasks. BitBake supports these types of
+functions:
+
+-  *Shell Functions:* Functions written in shell script and executed
+   either directly as functions, tasks, or both. They can also be called
+   by other shell functions.
+
+-  *BitBake-Style Python Functions:* Functions written in Python and
+   executed by BitBake or other Python functions using
+   ``bb.build.exec_func()``.
+
+-  *Python Functions:* Functions written in Python and executed by
+   Python.
+
+-  *Anonymous Python Functions:* Python functions executed automatically
+   during parsing.
+
+Regardless of the type of function, you can only define them in class
+(``.bbclass``) and recipe (``.bb`` or ``.inc``) files.
+
+Shell Functions
+---------------
+
+Functions written in shell script and executed either directly as
+functions, tasks, or both. They can also be called by other shell
+functions. Here is an example shell function definition: ::
+
+   some_function () {
+       echo "Hello World"
+   }
+
+When you create these types of functions in
+your recipe or class files, you need to follow the shell programming
+rules. The scripts are executed by ``/bin/sh``, which may not be a bash
+shell but might be something such as ``dash``. You should not use
+Bash-specific script (bashisms).
+
+Overrides and override-style operators like ``_append`` and ``_prepend``
+can also be applied to shell functions. Most commonly, this application
+would be used in a ``.bbappend`` file to modify functions in the main
+recipe. It can also be used to modify functions inherited from classes.
+
+As an example, consider the following: ::
+
+   do_foo() {
+       bbplain first
+       fn
+   }
+
+   fn_prepend() {
+       bbplain second
+   }
+
+   fn() {
+       bbplain third
+   }
+
+   do_foo_append() {
+       bbplain fourth
+   }
+
+Running ``do_foo`` prints the following: ::
+
+   recipename do_foo: first
+   recipename do_foo: second
+   recipename do_foo: third
+   recipename do_foo: fourth
+
+.. note::
+
+   Overrides and override-style operators can be applied to any shell
+   function, not just :ref:`tasks <bitbake-user-manual/bitbake-user-manual-metadata:tasks>`.
+
+You can use the ``bitbake -e`` recipename command to view the final
+assembled function after all overrides have been applied.
+
+BitBake-Style Python Functions
+------------------------------
+
+These functions are written in Python and executed by BitBake or other
+Python functions using ``bb.build.exec_func()``.
+
+An example BitBake function is: ::
+
+   python some_python_function () {
+       d.setVar("TEXT", "Hello World")
+       print d.getVar("TEXT")
+   }
+
+Because the
+Python "bb" and "os" modules are already imported, you do not need to
+import these modules. Also in these types of functions, the datastore
+("d") is a global variable and is always automatically available.
+
+.. note::
+
+   Variable expressions (e.g.  ``${X}`` ) are no longer expanded within Python
+   functions. This behavior is intentional in order to allow you to freely set
+   variable values to expandable expressions without having them expanded
+   prematurely. If you do wish to expand a variable within a Python function,
+   use ``d.getVar("X")`` . Or, for more complicated expressions, use ``d.expand()``.
+
+Similar to shell functions, you can also apply overrides and
+override-style operators to BitBake-style Python functions.
+
+As an example, consider the following: ::
+
+   python do_foo_prepend() {
+       bb.plain("first")
+   }
+
+   python do_foo() {
+       bb.plain("second")
+   }
+
+   python do_foo_append() {
+       bb.plain("third")
+   }
+
+Running ``do_foo`` prints the following: ::
+
+   recipename do_foo: first
+   recipename do_foo: second
+   recipename do_foo: third
+
+You can use the ``bitbake -e`` recipename command to view
+the final assembled function after all overrides have been applied.
+
+Python Functions
+----------------
+
+These functions are written in Python and are executed by other Python
+code. Examples of Python functions are utility functions that you intend
+to call from in-line Python or from within other Python functions. Here
+is an example: ::
+
+   def get_depends(d):
+       if d.getVar('SOMECONDITION'):
+           return "dependencywithcond"
+       else:
+           return "dependency"
+
+   SOMECONDITION = "1"
+   DEPENDS = "${@get_depends(d)}"
+
+This would result in ``DEPENDS`` containing ``dependencywithcond``.
+
+Here are some things to know about Python functions:
+
+-  Python functions can take parameters.
+
+-  The BitBake datastore is not automatically available. Consequently,
+   you must pass it in as a parameter to the function.
+
+-  The "bb" and "os" Python modules are automatically available. You do
+   not need to import them.
+
+BitBake-Style Python Functions Versus Python Functions
+------------------------------------------------------
+
+Following are some important differences between BitBake-style Python
+functions and regular Python functions defined with "def":
+
+-  Only BitBake-style Python functions can be :ref:`tasks <bitbake-user-manual/bitbake-user-manual-metadata:tasks>`.
+
+-  Overrides and override-style operators can only be applied to
+   BitBake-style Python functions.
+
+-  Only regular Python functions can take arguments and return values.
+
+-  :ref:`Variable flags <bitbake-user-manual/bitbake-user-manual-metadata:variable flags>` such as
+   ``[dirs]``, ``[cleandirs]``, and ``[lockfiles]`` can be used on BitBake-style
+   Python functions, but not on regular Python functions.
+
+-  BitBake-style Python functions generate a separate
+   ``${``\ :term:`T`\ ``}/run.``\ function-name\ ``.``\ pid
+   script that is executed to run the function, and also generate a log
+   file in ``${T}/log.``\ function-name\ ``.``\ pid if they are executed
+   as tasks.
+
+   Regular Python functions execute "inline" and do not generate any
+   files in ``${T}``.
+
+-  Regular Python functions are called with the usual Python syntax.
+   BitBake-style Python functions are usually tasks and are called
+   directly by BitBake, but can also be called manually from Python code
+   by using the ``bb.build.exec_func()`` function. Here is an example: ::
+
+      bb.build.exec_func("my_bitbake_style_function", d)
+
+   .. note::
+
+      ``bb.build.exec_func()`` can also be used to run shell functions from Python
+      code. If you want to run a shell function before a Python function within
+      the same task, then you can use a parent helper Python function that
+      starts by running the shell function with ``bb.build.exec_func()`` and then
+      runs the Python code.
+
+   To detect errors from functions executed with
+   ``bb.build.exec_func()``, you can catch the ``bb.build.FuncFailed``
+   exception.
+
+   .. note::
+
+      Functions in metadata (recipes and classes) should not themselves raise
+      ``bb.build.FuncFailed``. Rather, ``bb.build.FuncFailed`` should be viewed as a
+      general indicator that the called function failed by raising an
+      exception. For example, an exception raised by ``bb.fatal()`` will be caught
+      inside ``bb.build.exec_func()``, and a ``bb.build.FuncFailed`` will be raised in
+      response.
+
+Due to their simplicity, you should prefer regular Python functions over
+BitBake-style Python functions unless you need a feature specific to
+BitBake-style Python functions. Regular Python functions in metadata are
+a more recent invention than BitBake-style Python functions, and older
+code tends to use ``bb.build.exec_func()`` more often.
+
+Anonymous Python Functions
+--------------------------
+
+Sometimes it is useful to set variables or perform other operations
+programmatically during parsing. To do this, you can define special
+Python functions, called anonymous Python functions, that run at the end
+of parsing. For example, the following conditionally sets a variable
+based on the value of another variable: ::
+
+   python () {
+       if d.getVar('SOMEVAR') == 'value':
+           d.setVar('ANOTHERVAR', 'value2')
+   }
+
+An equivalent way to mark a function as an anonymous function is to give it
+the name "__anonymous", rather than no name.
+
+Anonymous Python functions always run at the end of parsing, regardless
+of where they are defined. If a recipe contains many anonymous
+functions, they run in the same order as they are defined within the
+recipe. As an example, consider the following snippet: ::
+
+   python () {
+       d.setVar('FOO', 'foo 2')
+   }
+
+   FOO = "foo 1"
+
+   python () {
+       d.appendVar('BAR',' bar 2')
+   }
+
+   BAR = "bar 1"
+
+The previous example is conceptually
+equivalent to the following snippet: ::
+
+   FOO = "foo 1"
+   BAR = "bar 1"
+   FOO = "foo 2"
+   BAR += "bar 2"
+
+``FOO`` ends up with the value "foo 2", and
+``BAR`` with the value "bar 1 bar 2". Just as in the second snippet, the
+values set for the variables within the anonymous functions become
+available to tasks, which always run after parsing.
+
+Overrides and override-style operators such as "``_append``" are applied
+before anonymous functions run. In the following example, ``FOO`` ends
+up with the value "foo from anonymous": ::
+
+   FOO = "foo"
+   FOO_append = " from outside"
+
+   python () {
+       d.setVar("FOO", "foo from anonymous")
+   }
+
+For methods
+you can use with anonymous Python functions, see the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:functions you can call from within python`"
+section. For a different method to run Python code during parsing, see
+the ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:inline python variable expansion`" section.
+
+Flexible Inheritance for Class Functions
+----------------------------------------
+
+Through coding techniques and the use of ``EXPORT_FUNCTIONS``, BitBake
+supports exporting a function from a class such that the class function
+appears as the default implementation of the function, but can still be
+called if a recipe inheriting the class needs to define its own version
+of the function.
+
+To understand the benefits of this feature, consider the basic scenario
+where a class defines a task function and your recipe inherits the
+class. In this basic scenario, your recipe inherits the task function as
+defined in the class. If desired, your recipe can add to the start and
+end of the function by using the "_prepend" or "_append" operations
+respectively, or it can redefine the function completely. However, if it
+redefines the function, there is no means for it to call the class
+version of the function. ``EXPORT_FUNCTIONS`` provides a mechanism that
+enables the recipe's version of the function to call the original
+version of the function.
+
+To make use of this technique, you need the following things in place:
+
+-  The class needs to define the function as follows: ::
+
+      classname_functionname
+
+   For example, if you have a class file
+   ``bar.bbclass`` and a function named ``do_foo``, the class must
+   define the function as follows: ::
+
+      bar_do_foo
+
+-  The class needs to contain the ``EXPORT_FUNCTIONS`` statement as
+   follows: ::
+
+      EXPORT_FUNCTIONS functionname
+
+   For example, continuing with
+   the same example, the statement in the ``bar.bbclass`` would be as
+   follows: ::
+
+      EXPORT_FUNCTIONS do_foo
+
+-  You need to call the function appropriately from within your recipe.
+   Continuing with the same example, if your recipe needs to call the
+   class version of the function, it should call ``bar_do_foo``.
+   Assuming ``do_foo`` was a shell function and ``EXPORT_FUNCTIONS`` was
+   used as above, the recipe's function could conditionally call the
+   class version of the function as follows: ::
+
+      do_foo() {
+          if [ somecondition ] ; then
+              bar_do_foo
+          else
+              # Do something else
+          fi
+      }
+
+   To call your modified version of the function as defined in your recipe,
+   call it as ``do_foo``.
+
+With these conditions met, your single recipe can freely choose between
+the original function as defined in the class file and the modified
+function in your recipe. If you do not set up these conditions, you are
+limited to using one function or the other.
+
+Tasks
+=====
+
+Tasks are BitBake execution units that make up the steps that BitBake
+can run for a given recipe. Tasks are only supported in recipes and
+classes (i.e. in ``.bb`` files and files included or inherited from
+``.bb`` files). By convention, tasks have names that start with "do\_".
+
+Promoting a Function to a Task
+------------------------------
+
+Tasks are either :ref:`shell functions <bitbake-user-manual/bitbake-user-manual-metadata:shell functions>` or
+:ref:`BitBake-style Python functions <bitbake-user-manual/bitbake-user-manual-metadata:bitbake-style python functions>`
+that have been promoted to tasks by using the ``addtask`` command. The
+``addtask`` command can also optionally describe dependencies between
+the task and other tasks. Here is an example that shows how to define a
+task and declare some dependencies: ::
+
+   python do_printdate () {
+       import time
+       print time.strftime('%Y%m%d', time.gmtime())
+   }
+   addtask printdate after do_fetch before do_build
+
+The first argument to ``addtask`` is the name
+of the function to promote to a task. If the name does not start with
+"do\_", "do\_" is implicitly added, which enforces the convention that all
+task names start with "do\_".
+
+In the previous example, the ``do_printdate`` task becomes a dependency
+of the ``do_build`` task, which is the default task (i.e. the task run
+by the ``bitbake`` command unless another task is specified explicitly).
+Additionally, the ``do_printdate`` task becomes dependent upon the
+``do_fetch`` task. Running the ``do_build`` task results in the
+``do_printdate`` task running first.
+
+.. note::
+
+   If you try out the previous example, you might see that the
+   ``do_printdate``
+   task is only run the first time you build the recipe with the
+   ``bitbake``
+   command. This is because BitBake considers the task "up-to-date"
+   after that initial run. If you want to force the task to always be
+   rerun for experimentation purposes, you can make BitBake always
+   consider the task "out-of-date" by using the
+   :ref:`[nostamp] <bitbake-user-manual/bitbake-user-manual-metadata:Variable Flags>`
+   variable flag, as follows: ::
+
+      do_printdate[nostamp] = "1"
+
+   You can also explicitly run the task and provide the
+   -f option as follows: ::
+
+      $ bitbake recipe -c printdate -f
+
+   When manually selecting a task to run with the bitbake ``recipe
+   -c task`` command, you can omit the "do\_" prefix as part of the task
+   name.
+
+You might wonder about the practical effects of using ``addtask``
+without specifying any dependencies as is done in the following example: ::
+
+   addtask printdate
+
+In this example, assuming dependencies have not been
+added through some other means, the only way to run the task is by
+explicitly selecting it with ``bitbake`` recipe ``-c printdate``. You
+can use the ``do_listtasks`` task to list all tasks defined in a recipe
+as shown in the following example: ::
+
+   $ bitbake recipe -c listtasks
+
+For more information on task dependencies, see the
+":ref:`bitbake-user-manual/bitbake-user-manual-execution:dependencies`" section.
+
+See the ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:variable flags`" section for information
+on variable flags you can use with tasks.
+
+.. note::
+
+   While it's infrequent, it's possible to define multiple tasks as
+   dependencies when calling ``addtask``. For example, here's a snippet
+   from the OpenEmbedded class file ``package_tar.bbclass``::
+
+     addtask package_write_tar before do_build after do_packagedata do_package
+
+   Note how the ``package_write_tar`` task has to wait until both of
+   ``do_packagedata`` and ``do_package`` complete.
+
+Deleting a Task
+---------------
+
+As well as being able to add tasks, you can delete them. Simply use the
+``deltask`` command to delete a task. For example, to delete the example
+task used in the previous sections, you would use: ::
+
+   deltask printdate
+
+If you delete a task using the ``deltask`` command and the task has
+dependencies, the dependencies are not reconnected. For example, suppose
+you have three tasks named ``do_a``, ``do_b``, and ``do_c``.
+Furthermore, ``do_c`` is dependent on ``do_b``, which in turn is
+dependent on ``do_a``. Given this scenario, if you use ``deltask`` to
+delete ``do_b``, the implicit dependency relationship between ``do_c``
+and ``do_a`` through ``do_b`` no longer exists, and ``do_c``
+dependencies are not updated to include ``do_a``. Thus, ``do_c`` is free
+to run before ``do_a``.
+
+If you want dependencies such as these to remain intact, use the
+``[noexec]`` varflag to disable the task instead of using the
+``deltask`` command to delete it: ::
+
+   do_b[noexec] = "1"
+
+Passing Information Into the Build Task Environment
+---------------------------------------------------
+
+When running a task, BitBake tightly controls the shell execution
+environment of the build tasks to make sure unwanted contamination from
+the build machine cannot influence the build.
+
+.. note::
+
+   By default, BitBake cleans the environment to include only those
+   things exported or listed in its whitelist to ensure that the build
+   environment is reproducible and consistent. You can prevent this
+   "cleaning" by setting the :term:`BB_PRESERVE_ENV` variable.
+
+Consequently, if you do want something to get passed into the build task
+environment, you must take these two steps:
+
+#. Tell BitBake to load what you want from the environment into the
+   datastore. You can do so through the
+   :term:`BB_ENV_WHITELIST` and
+   :term:`BB_ENV_EXTRAWHITE` variables. For
+   example, assume you want to prevent the build system from accessing
+   your ``$HOME/.ccache`` directory. The following command "whitelists"
+   the environment variable ``CCACHE_DIR`` causing BitBake to allow that
+   variable into the datastore: ::
+
+      export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"
+
+#. Tell BitBake to export what you have loaded into the datastore to the
+   task environment of every running task. Loading something from the
+   environment into the datastore (previous step) only makes it
+   available in the datastore. To export it to the task environment of
+   every running task, use a command similar to the following in your
+   local configuration file ``local.conf`` or your distribution
+   configuration file: ::
+
+      export CCACHE_DIR
+
+   .. note::
+
+      A side effect of the previous steps is that BitBake records the
+      variable as a dependency of the build process in things like the
+      setscene checksums. If doing so results in unnecessary rebuilds of
+      tasks, you can whitelist the variable so that the setscene code
+      ignores the dependency when it creates checksums.
+
+Sometimes, it is useful to be able to obtain information from the
+original execution environment. BitBake saves a copy of the original
+environment into a special variable named :term:`BB_ORIGENV`.
+
+The ``BB_ORIGENV`` variable returns a datastore object that can be
+queried using the standard datastore operators such as
+``getVar(, False)``. The datastore object is useful, for example, to
+find the original ``DISPLAY`` variable. Here is an example: ::
+
+   origenv = d.getVar("BB_ORIGENV", False)
+   bar = origenv.getVar("BAR", False)
+
+The previous example returns ``BAR`` from the original execution
+environment.
+
+Variable Flags
+==============
+
+Variable flags (varflags) help control a task's functionality and
+dependencies. BitBake reads and writes varflags to the datastore using
+the following command forms: ::
+
+   variable = d.getVarFlags("variable")
+   self.d.setVarFlags("FOO", {"func": True})
+
+When working with varflags, the same syntax, with the exception of
+overrides, applies. In other words, you can set, append, and prepend
+varflags just like variables. See the
+":ref:`bitbake-user-manual/bitbake-user-manual-metadata:variable flag syntax`" section for details.
+
+BitBake has a defined set of varflags available for recipes and classes.
+Tasks support a number of these flags which control various
+functionality of the task:
+
+-  ``[cleandirs]``: Empty directories that should be created before
+   the task runs. Directories that already exist are removed and
+   recreated to empty them.
+
+-  ``[depends]``: Controls inter-task dependencies. See the
+   :term:`DEPENDS` variable and the
+   ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:inter-task
+   dependencies`" section for more information.
+
+-  ``[deptask]``: Controls task build-time dependencies. See the
+   :term:`DEPENDS` variable and the ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:build dependencies`" section for more information.
+
+-  ``[dirs]``: Directories that should be created before the task
+   runs. Directories that already exist are left as is. The last
+   directory listed is used as the current working directory for the
+   task.
+
+-  ``[lockfiles]``: Specifies one or more lockfiles to lock while the
+   task executes. Only one task may hold a lockfile, and any task that
+   attempts to lock an already locked file will block until the lock is
+   released. You can use this variable flag to accomplish mutual
+   exclusion.
+
+-  ``[noexec]``: When set to "1", marks the task as being empty, with
+   no execution required. You can use the ``[noexec]`` flag to set up
+   tasks as dependency placeholders, or to disable tasks defined
+   elsewhere that are not needed in a particular recipe.
+
+-  ``[nostamp]``: When set to "1", tells BitBake to not generate a
+   stamp file for a task, which implies the task should always be
+   executed.
+
+   .. caution::
+
+      Any task that depends (possibly indirectly) on a ``[nostamp]`` task will
+      always be executed as well. This can cause unnecessary rebuilding if you
+      are not careful.
+
+-  ``[number_threads]``: Limits tasks to a specific number of
+   simultaneous threads during execution. This varflag is useful when
+   your build host has a large number of cores but certain tasks need to
+   be rate-limited due to various kinds of resource constraints (e.g. to
+   avoid network throttling). ``number_threads`` works similarly to the
+   :term:`BB_NUMBER_THREADS` variable but is task-specific.
+
+   Set the value globally. For example, the following makes sure the
+   ``do_fetch`` task uses no more than two simultaneous execution
+   threads: do_fetch[number_threads] = "2"
+
+   .. warning::
+
+      -  Setting the varflag in individual recipes rather than globally
+         can result in unpredictable behavior.
+
+      -  Setting the varflag to a value greater than the value used in
+         the ``BB_NUMBER_THREADS`` variable causes ``number_threads`` to
+         have no effect.
+
+-  ``[postfuncs]``: List of functions to call after the completion of
+   the task.
+
+-  ``[prefuncs]``: List of functions to call before the task executes.
+
+-  ``[rdepends]``: Controls inter-task runtime dependencies. See the
+   :term:`RDEPENDS` variable, the
+   :term:`RRECOMMENDS` variable, and the
+   ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:inter-task dependencies`" section for
+   more information.
+
+-  ``[rdeptask]``: Controls task runtime dependencies. See the
+   :term:`RDEPENDS` variable, the
+   :term:`RRECOMMENDS` variable, and the
+   ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:runtime dependencies`" section for more
+   information.
+
+-  ``[recideptask]``: When set in conjunction with ``recrdeptask``,
+   specifies a task that should be inspected for additional
+   dependencies.
+
+-  ``[recrdeptask]``: Controls task recursive runtime dependencies.
+   See the :term:`RDEPENDS` variable, the
+   :term:`RRECOMMENDS` variable, and the
+   ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:recursive dependencies`" section for
+   more information.
+
+-  ``[stamp-extra-info]``: Extra stamp information to append to the
+   task's stamp. As an example, OpenEmbedded uses this flag to allow
+   machine-specific tasks.
+
+-  ``[umask]``: The umask to run the task under.
+
+Several varflags are useful for controlling how signatures are
+calculated for variables. For more information on this process, see the
+":ref:`bitbake-user-manual/bitbake-user-manual-execution:checksums (signatures)`" section.
+
+-  ``[vardeps]``: Specifies a space-separated list of additional
+   variables to add to a variable's dependencies for the purposes of
+   calculating its signature. Adding variables to this list is useful,
+   for example, when a function refers to a variable in a manner that
+   does not allow BitBake to automatically determine that the variable
+   is referred to.
+
+-  ``[vardepsexclude]``: Specifies a space-separated list of variables
+   that should be excluded from a variable's dependencies for the
+   purposes of calculating its signature.
+
+-  ``[vardepvalue]``: If set, instructs BitBake to ignore the actual
+   value of the variable and instead use the specified value when
+   calculating the variable's signature.
+
+-  ``[vardepvalueexclude]``: Specifies a pipe-separated list of
+   strings to exclude from the variable's value when calculating the
+   variable's signature.
+
+Events
+======
+
+BitBake allows installation of event handlers within recipe and class
+files. Events are triggered at certain points during operation, such as
+the beginning of operation against a given recipe (i.e. ``*.bb``), the
+start of a given task, a task failure, a task success, and so forth. The
+intent is to make it easy to do things like email notification on build
+failures.
+
+Following is an example event handler that prints the name of the event
+and the content of the ``FILE`` variable: ::
+
+   addhandler myclass_eventhandler
+   python myclass_eventhandler() {
+       from bb.event import getName
+       print("The name of the Event is %s" % getName(e))
+       print("The file we run for is %s" % d.getVar('FILE'))
+   }
+   myclass_eventhandler[eventmask] = "bb.event.BuildStarted
+   bb.event.BuildCompleted"
+
+In the previous example, an eventmask has been
+set so that the handler only sees the "BuildStarted" and
+"BuildCompleted" events. This event handler gets called every time an
+event matching the eventmask is triggered. A global variable "e" is
+defined, which represents the current event. With the ``getName(e)``
+method, you can get the name of the triggered event. The global
+datastore is available as "d". In legacy code, you might see "e.data"
+used to get the datastore. However, realize that "e.data" is deprecated
+and you should use "d" going forward.
+
+The context of the datastore is appropriate to the event in question.
+For example, "BuildStarted" and "BuildCompleted" events run before any
+tasks are executed so would be in the global configuration datastore
+namespace. No recipe-specific metadata exists in that namespace. The
+"BuildStarted" and "BuildCompleted" events also run in the main
+cooker/server process rather than any worker context. Thus, any changes
+made to the datastore would be seen by other cooker/server events within
+the current build but not seen outside of that build or in any worker
+context. Task events run in the actual tasks in question consequently
+have recipe-specific and task-specific contents. These events run in the
+worker context and are discarded at the end of task execution.
+
+During a standard build, the following common events might occur. The
+following events are the most common kinds of events that most metadata
+might have an interest in viewing:
+
+-  ``bb.event.ConfigParsed()``: Fired when the base configuration; which
+   consists of ``bitbake.conf``, ``base.bbclass`` and any global
+   ``INHERIT`` statements; has been parsed. You can see multiple such
+   events when each of the workers parse the base configuration or if
+   the server changes configuration and reparses. Any given datastore
+   only has one such event executed against it, however. If
+   :term:`BB_INVALIDCONF` is set in the datastore by the event
+   handler, the configuration is reparsed and a new event triggered,
+   allowing the metadata to update configuration.
+
+-  ``bb.event.HeartbeatEvent()``: Fires at regular time intervals of one
+   second. You can configure the interval time using the
+   ``BB_HEARTBEAT_EVENT`` variable. The event's "time" attribute is the
+   ``time.time()`` value when the event is triggered. This event is
+   useful for activities such as system state monitoring.
+
+-  ``bb.event.ParseStarted()``: Fired when BitBake is about to start
+   parsing recipes. This event's "total" attribute represents the number
+   of recipes BitBake plans to parse.
+
+-  ``bb.event.ParseProgress()``: Fired as parsing progresses. This
+   event's "current" attribute is the number of recipes parsed as well
+   as the "total" attribute.
+
+-  ``bb.event.ParseCompleted()``: Fired when parsing is complete. This
+   event's "cached", "parsed", "skipped", "virtuals", "masked", and
+   "errors" attributes provide statistics for the parsing results.
+
+-  ``bb.event.BuildStarted()``: Fired when a new build starts. BitBake
+   fires multiple "BuildStarted" events (one per configuration) when
+   multiple configuration (multiconfig) is enabled.
+
+-  ``bb.build.TaskStarted()``: Fired when a task starts. This event's
+   "taskfile" attribute points to the recipe from which the task
+   originates. The "taskname" attribute, which is the task's name,
+   includes the ``do_`` prefix, and the "logfile" attribute point to
+   where the task's output is stored. Finally, the "time" attribute is
+   the task's execution start time.
+
+-  ``bb.build.TaskInvalid()``: Fired if BitBake tries to execute a task
+   that does not exist.
+
+-  ``bb.build.TaskFailedSilent()``: Fired for setscene tasks that fail
+   and should not be presented to the user verbosely.
+
+-  ``bb.build.TaskFailed()``: Fired for normal tasks that fail.
+
+-  ``bb.build.TaskSucceeded()``: Fired when a task successfully
+   completes.
+
+-  ``bb.event.BuildCompleted()``: Fired when a build finishes.
+
+-  ``bb.cooker.CookerExit()``: Fired when the BitBake server/cooker
+   shuts down. This event is usually only seen by the UIs as a sign they
+   should also shutdown.
+
+This next list of example events occur based on specific requests to the
+server. These events are often used to communicate larger pieces of
+information from the BitBake server to other parts of BitBake such as
+user interfaces:
+
+-  ``bb.event.TreeDataPreparationStarted()``
+-  ``bb.event.TreeDataPreparationProgress()``
+-  ``bb.event.TreeDataPreparationCompleted()``
+-  ``bb.event.DepTreeGenerated()``
+-  ``bb.event.CoreBaseFilesFound()``
+-  ``bb.event.ConfigFilePathFound()``
+-  ``bb.event.FilesMatchingFound()``
+-  ``bb.event.ConfigFilesFound()``
+-  ``bb.event.TargetsTreeGenerated()``
+
+.. _variants-class-extension-mechanism:
+
+Variants - Class Extension Mechanism
+====================================
+
+BitBake supports two features that facilitate creating from a single
+recipe file multiple incarnations of that recipe file where all
+incarnations are buildable. These features are enabled through the
+:term:`BBCLASSEXTEND` and :term:`BBVERSIONS` variables.
+
+.. note::
+
+   The mechanism for this class extension is extremely specific to the
+   implementation. Usually, the recipe's :term:`PROVIDES` , :term:`PN` , and
+   :term:`DEPENDS` variables would need to be modified by the extension
+   class. For specific examples, see the OE-Core native , nativesdk , and
+   multilib classes.
+
+-  ``BBCLASSEXTEND``: This variable is a space separated list of
+   classes used to "extend" the recipe for each variant. Here is an
+   example that results in a second incarnation of the current recipe
+   being available. This second incarnation will have the "native" class
+   inherited. ::
+
+      BBCLASSEXTEND = "native"
+
+-  ``BBVERSIONS``: This variable allows a single recipe to build
+   multiple versions of a project from a single recipe file. You can
+   also specify conditional metadata (using the
+   :term:`OVERRIDES` mechanism) for a single
+   version, or an optionally named range of versions. Here is an
+   example: ::
+
+      BBVERSIONS = "1.0 2.0 git"
+      SRC_URI_git = "git://someurl/somepath.git"
+
+      BBVERSIONS = "1.0.[0-6]:1.0.0+ 1.0.[7-9]:1.0.7+"
+      SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;patch=1"
+
+   The name of the range defaults to the original version of the recipe. For
+   example, in OpenEmbedded, the recipe file ``foo_1.0.0+.bb`` creates a default
+   name range of ``1.0.0+``. This is useful because the range name is not only
+   placed into overrides, but it is also made available for the metadata to use
+   in the variable that defines the base recipe versions for use in ``file://``
+   search paths (:term:`FILESPATH`).
+
+Dependencies
+============
+
+To allow for efficient parallel processing, BitBake handles dependencies
+at the task level. Dependencies can exist both between tasks within a
+single recipe and between tasks in different recipes. Following are
+examples of each:
+
+-  For tasks within a single recipe, a recipe's ``do_configure`` task
+   might need to complete before its ``do_compile`` task can run.
+
+-  For tasks in different recipes, one recipe's ``do_configure`` task
+   might require another recipe's ``do_populate_sysroot`` task to finish
+   first such that the libraries and headers provided by the other
+   recipe are available.
+
+This section describes several ways to declare dependencies. Remember,
+even though dependencies are declared in different ways, they are all
+simply dependencies between tasks.
+
+.. _dependencies-internal-to-the-bb-file:
+
+Dependencies Internal to the ``.bb`` File
+-----------------------------------------
+
+BitBake uses the ``addtask`` directive to manage dependencies that are
+internal to a given recipe file. You can use the ``addtask`` directive
+to indicate when a task is dependent on other tasks or when other tasks
+depend on that recipe. Here is an example: ::
+
+   addtask printdate after do_fetch before do_build
+
+In this example, the ``do_printdate`` task
+depends on the completion of the ``do_fetch`` task, and the ``do_build``
+task depends on the completion of the ``do_printdate`` task.
+
+.. note::
+
+   For a task to run, it must be a direct or indirect dependency of some
+   other task that is scheduled to run.
+
+   For illustration, here are some examples:
+
+   -  The directive ``addtask mytask before do_configure`` causes
+      ``do_mytask`` to run before ``do_configure`` runs. Be aware that
+      ``do_mytask`` still only runs if its :ref:`input
+      checksum <bitbake-user-manual/bitbake-user-manual-execution:checksums (signatures)>` has changed since the last time it was
+      run. Changes to the input checksum of ``do_mytask`` also
+      indirectly cause ``do_configure`` to run.
+
+   -  The directive ``addtask mytask after do_configure`` by itself
+      never causes ``do_mytask`` to run. ``do_mytask`` can still be run
+      manually as follows: ::
+
+         $ bitbake recipe -c mytask
+
+      Declaring ``do_mytask`` as a dependency of some other task that is
+      scheduled to run also causes it to run. Regardless, the task runs after
+      ``do_configure``.
+
+Build Dependencies
+------------------
+
+BitBake uses the :term:`DEPENDS` variable to manage
+build time dependencies. The ``[deptask]`` varflag for tasks signifies
+the task of each item listed in ``DEPENDS`` that must complete before
+that task can be executed. Here is an example: ::
+
+   do_configure[deptask] = "do_populate_sysroot"
+
+In this example, the ``do_populate_sysroot`` task
+of each item in ``DEPENDS`` must complete before ``do_configure`` can
+execute.
+
+Runtime Dependencies
+--------------------
+
+BitBake uses the :term:`PACKAGES`, :term:`RDEPENDS`, and :term:`RRECOMMENDS`
+variables to manage runtime dependencies.
+
+The ``PACKAGES`` variable lists runtime packages. Each of those packages
+can have ``RDEPENDS`` and ``RRECOMMENDS`` runtime dependencies. The
+``[rdeptask]`` flag for tasks is used to signify the task of each item
+runtime dependency which must have completed before that task can be
+executed. ::
+
+   do_package_qa[rdeptask] = "do_packagedata"
+
+In the previous
+example, the ``do_packagedata`` task of each item in ``RDEPENDS`` must
+have completed before ``do_package_qa`` can execute.
+Although ``RDEPENDS`` contains entries from the
+runtime dependency namespace, BitBake knows how to map them back
+to the build-time dependency namespace, in which the tasks are defined.
+
+Recursive Dependencies
+----------------------
+
+BitBake uses the ``[recrdeptask]`` flag to manage recursive task
+dependencies. BitBake looks through the build-time and runtime
+dependencies of the current recipe, looks through the task's inter-task
+dependencies, and then adds dependencies for the listed task. Once
+BitBake has accomplished this, it recursively works through the
+dependencies of those tasks. Iterative passes continue until all
+dependencies are discovered and added.
+
+The ``[recrdeptask]`` flag is most commonly used in high-level recipes
+that need to wait for some task to finish "globally". For example,
+``image.bbclass`` has the following: ::
+
+   do_rootfs[recrdeptask] += "do_packagedata"
+
+This statement says that the ``do_packagedata`` task of
+the current recipe and all recipes reachable (by way of dependencies)
+from the image recipe must run before the ``do_rootfs`` task can run.
+
+BitBake allows a task to recursively depend on itself by
+referencing itself in the task list: ::
+
+   do_a[recrdeptask] = "do_a do_b"
+
+In the same way as before, this means that the ``do_a``
+and ``do_b`` tasks of the current recipe and all
+recipes reachable (by way of dependencies) from the recipe
+must run before the ``do_a`` task can run. In this
+case BitBake will ignore the current recipe's ``do_a``
+task circular dependency on itself.
+
+Inter-Task Dependencies
+-----------------------
+
+BitBake uses the ``[depends]`` flag in a more generic form to manage
+inter-task dependencies. This more generic form allows for
+inter-dependency checks for specific tasks rather than checks for the
+data in ``DEPENDS``. Here is an example: ::
+
+   do_patch[depends] = "quilt-native:do_populate_sysroot"
+
+In this example, the ``do_populate_sysroot`` task of the target ``quilt-native``
+must have completed before the ``do_patch`` task can execute.
+
+The ``[rdepends]`` flag works in a similar way but takes targets in the
+runtime namespace instead of the build-time dependency namespace.
+
+Functions You Can Call From Within Python
+=========================================
+
+BitBake provides many functions you can call from within Python
+functions. This section lists the most commonly used functions, and
+mentions where to find others.
+
+Functions for Accessing Datastore Variables
+-------------------------------------------
+
+It is often necessary to access variables in the BitBake datastore using
+Python functions. The BitBake datastore has an API that allows you this
+access. Here is a list of available operations:
+
+.. list-table::
+   :widths: auto
+   :header-rows: 1
+
+   * - *Operation*
+     - *Description*
+   * - ``d.getVar("X", expand)``
+     - Returns the value of variable "X". Using "expand=True" expands the
+       value. Returns "None" if the variable "X" does not exist.
+   * - ``d.setVar("X", "value")``
+     - Sets the variable "X" to "value"
+   * - ``d.appendVar("X", "value")``
+     - Adds "value" to the end of the variable "X". Acts like ``d.setVar("X",
+       "value")`` if the variable "X" does not exist.
+   * - ``d.prependVar("X", "value")``
+     - Adds "value" to the start of the variable "X". Acts like
+       ``d.setVar("X","value")`` if the variable "X" does not exist.
+   * - ``d.delVar("X")``
+     - Deletes the variable "X" from the datastore. Does nothing if the variable
+       "X" does not exist.
+   * - ``d.renameVar("X", "Y")``
+     - Renames the variable "X" to "Y". Does nothing if the variable "X" does
+       not exist.
+   * - ``d.getVarFlag("X", flag, expand)``
+     - Returns the value of variable "X". Using "expand=True" expands the
+       value. Returns "None" if either the variable "X" or the named flag does
+       not exist.
+   * - ``d.setVarFlag("X", flag, "value")``
+     - Sets the named flag for variable "X" to "value".
+   * - ``d.appendVarFlag("X", flag, "value")``
+     - Appends "value" to the named flag on the variable "X". Acts like
+       ``d.setVarFlag("X", flag, "value")`` if the named flag does not exist.
+   * - ``d.prependVarFlag("X", flag, "value")``
+     - Prepends "value" to the named flag on the variable "X". Acts like
+       ``d.setVarFlag("X", flag, "value")`` if the named flag does not exist.
+   * - ``d.delVarFlag("X", flag)``
+     - Deletes the named flag on the variable "X" from the datastore.
+   * - ``d.setVarFlags("X", flagsdict)``
+     - Sets the flags specified in the ``flagsdict()``
+       parameter. ``setVarFlags`` does not clear previous flags. Think of this
+       operation as ``addVarFlags``.
+   * - ``d.getVarFlags("X")``
+     - Returns a ``flagsdict`` of the flags for the variable "X". Returns "None"
+       if the variable "X" does not exist.
+   * - ``d.delVarFlags("X")``
+     - Deletes all the flags for the variable "X". Does nothing if the variable
+       "X" does not exist.
+   * - ``d.expand(expression)``
+     - Expands variable references in the specified string
+       expression. References to variables that do not exist are left as is. For
+       example, ``d.expand("foo ${X}")`` expands to the literal string "foo
+       ${X}" if the variable "X" does not exist.
+
+Other Functions
+---------------
+
+You can find many other functions that can be called from Python by
+looking at the source code of the ``bb`` module, which is in
+``bitbake/lib/bb``. For example, ``bitbake/lib/bb/utils.py`` includes
+the commonly used functions ``bb.utils.contains()`` and
+``bb.utils.mkdirhier()``, which come with docstrings.
+
+Task Checksums and Setscene
+===========================
+
+BitBake uses checksums (or signatures) along with the setscene to
+determine if a task needs to be run. This section describes the process.
+To help understand how BitBake does this, the section assumes an
+OpenEmbedded metadata-based example.
+
+These checksums are stored in :term:`STAMP`. You can
+examine the checksums using the following BitBake command: ::
+
+   $ bitbake-dumpsigs
+
+This command returns the signature data in a readable
+format that allows you to examine the inputs used when the OpenEmbedded
+build system generates signatures. For example, using
+``bitbake-dumpsigs`` allows you to examine the ``do_compile`` task's
+"sigdata" for a C application (e.g. ``bash``). Running the command also
+reveals that the "CC" variable is part of the inputs that are hashed.
+Any changes to this variable would invalidate the stamp and cause the
+``do_compile`` task to run.
+
+The following list describes related variables:
+
+-  :term:`BB_HASHCHECK_FUNCTION`:
+   Specifies the name of the function to call during the "setscene" part
+   of the task's execution in order to validate the list of task hashes.
+
+-  :term:`BB_SETSCENE_DEPVALID`:
+   Specifies a function BitBake calls that determines whether BitBake
+   requires a setscene dependency to be met.
+
+-  :term:`BB_SETSCENE_VERIFY_FUNCTION2`:
+   Specifies a function to call that verifies the list of planned task
+   execution before the main task execution happens.
+
+-  :term:`BB_STAMP_POLICY`: Defines the mode
+   for comparing timestamps of stamp files.
+
+-  :term:`BB_STAMP_WHITELIST`: Lists stamp
+   files that are looked at when the stamp policy is "whitelist".
+
+-  :term:`BB_TASKHASH`: Within an executing task,
+   this variable holds the hash of the task as returned by the currently
+   enabled signature generator.
+
+-  :term:`STAMP`: The base path to create stamp files.
+
+-  :term:`STAMPCLEAN`: Again, the base path to
+   create stamp files but can use wildcards for matching a range of
+   files for clean operations.
+
+Wildcard Support in Variables
+=============================
+
+Support for wildcard use in variables varies depending on the context in
+which it is used. For example, some variables and file names allow
+limited use of wildcards through the "``%``" and "``*``" characters.
+Other variables or names support Python's
+`glob <https://docs.python.org/3/library/glob.html>`_ syntax,
+`fnmatch <https://docs.python.org/3/library/fnmatch.html#module-fnmatch>`_
+syntax, or
+`Regular Expression (re) <https://docs.python.org/3/library/re.html>`_
+syntax.
+
+For variables that have wildcard suport, the documentation describes
+which form of wildcard, its use, and its limitations.
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
deleted file mode 100644
index 0ca53216..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
+++ /dev/null
@@ -1,2862 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<chapter id="bitbake-user-manual-metadata">
-    <title>Syntax and Operators</title>
-
-    <para>
-        BitBake files have their own syntax.
-        The syntax has similarities to several
-        other languages but also has some unique features.
-        This section describes the available syntax and operators
-        as well as provides examples.
-    </para>
-
-    <section id='basic-syntax'>
-        <title>Basic Syntax</title>
-
-        <para>
-            This section provides some basic syntax examples.
-        </para>
-
-        <section id='basic-variable-setting'>
-            <title>Basic Variable Setting</title>
-
-            <para>
-                The following example sets <filename>VARIABLE</filename> to
-                "value".
-                This assignment occurs immediately as the statement is parsed.
-                It is a "hard" assignment.
-                <literallayout class='monospaced'>
-     VARIABLE = "value"
-                </literallayout>
-                As expected, if you include leading or trailing spaces as part of
-                an assignment, the spaces are retained:
-                <literallayout class='monospaced'>
-     VARIABLE = " value"
-     VARIABLE = "value "
-                </literallayout>
-                Setting <filename>VARIABLE</filename> to "" sets it to an empty string,
-                while setting the variable to " " sets it to a blank space
-                (i.e. these are not the same values).
-                <literallayout class='monospaced'>
-     VARIABLE = ""
-     VARIABLE = " "
-                </literallayout>
-            </para>
-
-            <para>
-                You can use single quotes instead of double quotes
-                when setting a variable's value.
-                Doing so allows you to use values that contain the double
-                quote character:
-                <literallayout class='monospaced'>
-     VARIABLE = 'I have a " in my value'
-                </literallayout>
-                <note>
-                    Unlike in Bourne shells, single quotes work identically
-                    to double quotes in all other ways.
-                    They do not suppress variable expansions.
-                </note>
-            </para>
-        </section>
-
-        <section id='modifying-existing-variables'>
-            <title>Modifying Existing Variables</title>
-
-            <para>
-                Sometimes you need to modify existing variables.
-                Following are some cases where you might find you want to
-                modify an existing variable:
-                <itemizedlist>
-                    <listitem><para>
-                        Customize a recipe that uses the variable.
-                        </para></listitem>
-                    <listitem><para>
-                        Change a variable's default value used in a
-                        <filename>*.bbclass</filename> file.
-                        </para></listitem>
-                    <listitem><para>
-                        Change the variable in a <filename>*.bbappend</filename>
-                        file to override the variable in the original recipe.
-                        </para></listitem>
-                    <listitem><para>
-                        Change the variable in a configuration file so that the
-                        value overrides an existing configuration.
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-
-            <para>
-                Changing a variable value can sometimes depend on how the
-                value was originally assigned and also on the desired
-                intent of the change.
-                In particular, when you append a value to a variable that
-                has a default value, the resulting value might not be what
-                you expect.
-                In this case, the value you provide might replace the value
-                rather than append to the default value.
-            </para>
-
-            <para>
-                If after you have changed a variable's value and something
-                unexplained occurs, you can use BitBake to check the actual
-                value of the suspect variable.
-                You can make these checks for both configuration and recipe
-                level changes:
-                <itemizedlist>
-                    <listitem><para>
-                        For configuration changes, use the following:
-                        <literallayout class='monospaced'>
-     $ bitbake -e
-                        </literallayout>
-                        This command displays variable values after the
-                        configuration files (i.e. <filename>local.conf</filename>,
-                        <filename>bblayers.conf</filename>,
-                        <filename>bitbake.conf</filename> and so forth) have
-                        been parsed.
-                        <note>
-                            Variables that are exported to the environment are
-                            preceded by the string "export" in the command's
-                            output.
-                        </note>
-                        </para></listitem>
-                    <listitem><para>
-                        For recipe changes, use the following:
-                        <literallayout class='monospaced'>
-     $ bitbake <replaceable>recipe</replaceable> -e | grep VARIABLE="
-                        </literallayout>
-                        This command checks to see if the variable actually
-                        makes it into a specific recipe.
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-        </section>
-
-        <section id='line-joining'>
-            <title>Line Joining</title>
-
-            <para>
-                Outside of
-                <link linkend='functions'>functions</link>, BitBake joins
-                any line ending in a backslash character ("\")
-                with the following line before parsing statements.
-                The most common use for the "\" character is to split variable
-                assignments over multiple lines, as in the following example:
-                <literallayout class='monospaced'>
-     FOO = "bar \
-            baz \
-            qaz"
-                </literallayout>
-                Both the "\" character and the newline character
-                that follow it are removed when joining lines.
-                Thus, no newline characters end up in the value of
-                <filename>FOO</filename>.
-            </para>
-
-            <para>
-                Consider this additional example where the two
-                assignments both assign "barbaz" to
-                <filename>FOO</filename>:
-                <literallayout class='monospaced'>
-     FOO = "barbaz"
-
-     FOO = "bar\
-     baz"
-                </literallayout>
-                <note>
-                    BitBake does not interpret escape sequences like
-                    "\n" in variable values.
-                    For these to have an effect, the value must be passed
-                    to some utility that interprets escape sequences,
-                    such as <filename>printf</filename> or
-                    <filename>echo -n</filename>.
-                </note>
-            </para>
-        </section>
-
-        <section id='variable-expansion'>
-            <title>Variable Expansion</title>
-
-            <para>
-                Variables can reference the contents of other variables
-                using a syntax that is similar to variable expansion in
-                Bourne shells.
-                The following assignments
-                result in A containing "aval" and B evaluating to "preavalpost".
-                <literallayout class='monospaced'>
-     A = "aval"
-     B = "pre${A}post"
-                </literallayout>
-                <note>
-                    Unlike in Bourne shells, the curly braces are mandatory:
-                    Only <filename>${FOO}</filename> and not
-                    <filename>$FOO</filename> is recognized as an expansion of
-                    <filename>FOO</filename>.
-                </note>
-                The "=" operator does not immediately expand variable
-                references in the right-hand side.
-                Instead, expansion is deferred until the variable assigned to
-                is actually used.
-                The result depends on the current values of the referenced
-                variables.
-                The following example should clarify this behavior:
-                <literallayout class='monospaced'>
-     A = "${B} baz"
-     B = "${C} bar"
-     C = "foo"
-     *At this point, ${A} equals "foo bar baz"*
-     C = "qux"
-     *At this point, ${A} equals "qux bar baz"*
-     B = "norf"
-     *At this point, ${A} equals "norf baz"*
-                </literallayout>
-                Contrast this behavior with the
-                <link linkend='immediate-variable-expansion'>immediate variable expansion</link>
-                operator (i.e. ":=").
-            </para>
-
-            <para>
-                If the variable expansion syntax is used on a variable that
-                does not exist, the string is kept as is.
-                For example, given the following assignment,
-                <filename>BAR</filename> expands to the literal string
-                "${FOO}" as long as <filename>FOO</filename> does not exist.
-                <literallayout class='monospaced'>
-     BAR = "${FOO}"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='setting-a-default-value'>
-            <title>Setting a default value (?=)</title>
-
-            <para>
-                You can use the "?=" operator to achieve a "softer" assignment
-                for a variable.
-                This type of assignment allows you to define a variable if it
-                is undefined when the statement is parsed, but to leave the
-                value alone if the variable has a value.
-                Here is an example:
-                <literallayout class='monospaced'>
-     A ?= "aval"
-                </literallayout>
-                If <filename>A</filename> is set at the time this statement is parsed,
-                the variable retains its value.
-                However, if <filename>A</filename> is not set,
-                the variable is set to "aval".
-                <note>
-                    This assignment is immediate.
-                    Consequently, if multiple "?=" assignments
-                    to a single variable exist, the first of those ends up getting
-                    used.
-                </note>
-            </para>
-        </section>
-
-        <section id='setting-a-weak-default-value'>
-            <title>Setting a weak default value (??=)</title>
-
-            <para>
-                It is possible to use a "weaker" assignment than in the
-                previous section by using the "??=" operator.
-                This assignment behaves identical to "?=" except that the
-                assignment is made at the end of the parsing process rather
-                than immediately.
-                Consequently, when multiple "??=" assignments exist, the last
-                one is used.
-                Also, any "=" or "?=" assignment will override the value set with
-                "??=".
-                Here is an example:
-                <literallayout class='monospaced'>
-     A ??= "somevalue"
-     A ??= "someothervalue"
-                </literallayout>
-                If <filename>A</filename> is set before the above statements are parsed,
-                the variable retains its value.
-                If <filename>A</filename> is not set,
-                the variable is set to "someothervalue".
-            </para>
-
-            <para>
-                Again, this assignment is a "lazy" or "weak" assignment
-                because it does not occur until the end
-                of the parsing process.
-            </para>
-        </section>
-
-        <section id='immediate-variable-expansion'>
-            <title>Immediate variable expansion (:=)</title>
-
-            <para>
-                The ":=" operator results in a variable's
-                contents being expanded immediately,
-                rather than when the variable is actually used:
-                <literallayout class='monospaced'>
-     T = "123"
-     A := "test ${T}"
-     T = "456"
-     B := "${T} ${C}"
-     C = "cval"
-     C := "${C}append"
-                </literallayout>
-                In this example, <filename>A</filename> contains
-                "test 123", even though the final value of <filename>T</filename>
-                is "456".
-                The variable <filename>B</filename> will end up containing "456 cvalappend".
-                This is because references to undefined variables are preserved as is
-                during (immediate)expansion. This is in contrast to GNU Make, where undefined
-                variables expand to nothing.
-                The variable <filename>C</filename>
-                contains "cvalappend" since <filename>${C}</filename> immediately
-                expands to "cval".
-            </para>
-        </section>
-
-        <section id='appending-and-prepending'>
-            <title>Appending (+=) and prepending (=+) With Spaces</title>
-
-            <para>
-                Appending and prepending values is common and can be accomplished
-                using the "+=" and "=+" operators.
-                These operators insert a space between the current
-                value and prepended or appended value.
-            </para>
-
-            <para>
-                These operators take immediate effect during parsing.
-                Here are some examples:
-                <literallayout class='monospaced'>
-     B = "bval"
-     B += "additionaldata"
-     C = "cval"
-     C =+ "test"
-                </literallayout>
-                The variable <filename>B</filename> contains
-                "bval additionaldata" and <filename>C</filename>
-                contains "test cval".
-            </para>
-        </section>
-
-        <section id='appending-and-prepending-without-spaces'>
-            <title>Appending (.=) and Prepending (=.) Without Spaces</title>
-
-            <para>
-                If you want to append or prepend values without an
-                inserted space, use the ".=" and "=." operators.
-            </para>
-
-            <para>
-                These operators take immediate effect during parsing.
-                Here are some examples:
-                <literallayout class='monospaced'>
-     B = "bval"
-     B .= "additionaldata"
-     C = "cval"
-     C =. "test"
-                </literallayout>
-                The variable <filename>B</filename> contains
-                "bvaladditionaldata" and
-                <filename>C</filename> contains "testcval".
-            </para>
-        </section>
-
-        <section id='appending-and-prepending-override-style-syntax'>
-            <title>Appending and Prepending (Override Style Syntax)</title>
-
-            <para>
-                You can also append and prepend a variable's value
-                using an override style syntax.
-                When you use this syntax, no spaces are inserted.
-            </para>
-
-            <para>
-                These operators differ from the ":=", ".=", "=.", "+=", and "=+"
-                operators in that their effects are applied at variable
-                expansion time rather than being immediately applied.
-                Here are some examples:
-                <literallayout class='monospaced'>
-     B = "bval"
-     B_append = " additional data"
-     C = "cval"
-     C_prepend = "additional data "
-     D = "dval"
-     D_append = "additional data"
-                </literallayout>
-                The variable <filename>B</filename> becomes
-                "bval additional data" and <filename>C</filename> becomes
-                "additional data cval".
-                The variable <filename>D</filename> becomes
-                "dvaladditional data".
-                <note>
-                    You must control all spacing when you use the
-                    override syntax.
-                </note>
-            </para>
-
-            <para>
-                It is also possible to append and prepend to shell
-                functions and BitBake-style Python functions.
-                See the
-                "<link linkend='shell-functions'>Shell Functions</link>" and
-                "<link linkend='bitbake-style-python-functions'>BitBake-Style Python Functions</link>
-                sections for examples.
-            </para>
-        </section>
-
-        <section id='removing-override-style-syntax'>
-            <title>Removal (Override Style Syntax)</title>
-
-            <para>
-                You can remove values from lists using the removal
-                override style syntax.
-                Specifying a value for removal causes all occurrences of that
-                value to be removed from the variable.
-            </para>
-
-            <para>
-                When you use this syntax, BitBake expects one or more strings.
-                Surrounding spaces and spacing are preserved.
-                Here is an example:
-                <literallayout class='monospaced'>
-     FOO = "123 456 789 123456 123 456 123 456"
-     FOO_remove = "123"
-     FOO_remove = "456"
-     FOO2 = " abc  def ghi abcdef abc def abc  def def"
-     FOO2_remove = " \
-         def \
-         abc \
-         ghi \
-     "
-                </literallayout>
-                The variable <filename>FOO</filename> becomes
-                "&nbsp;&nbsp;789&nbsp;123456&nbsp;&nbsp;&nbsp;&nbsp;"
-                and <filename>FOO2</filename> becomes
-                "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;abcdef&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".
-            </para>
-
-            <para>
-                Like "_append" and "_prepend", "_remove"
-                is applied at variable expansion time.
-            </para>
-        </section>
-
-        <section id='override-style-operation-advantages'>
-            <title>Override Style Operation Advantages</title>
-
-            <para>
-                An advantage of the override style operations
-                "_append", "_prepend", and "_remove" as compared to the
-                "+=" and "=+" operators is that the override style
-                operators provide guaranteed operations.
-                For example, consider a class <filename>foo.bbclass</filename>
-                that needs to add the value "val" to the variable
-                <filename>FOO</filename>, and a recipe that uses
-                <filename>foo.bbclass</filename> as follows:
-                <literallayout class='monospaced'>
-     inherit foo
-
-     FOO = "initial"
-                </literallayout>
-                If <filename>foo.bbclass</filename> uses the "+=" operator,
-                as follows, then the final value of <filename>FOO</filename>
-                will be "initial", which is not what is desired:
-                <literallayout class='monospaced'>
-     FOO += "val"
-                </literallayout>
-                If, on the other hand, <filename>foo.bbclass</filename>
-                uses the "_append" operator, then the final value of
-                <filename>FOO</filename> will be "initial val", as intended:
-                <literallayout class='monospaced'>
-     FOO_append = " val"
-                </literallayout>
-                <note>
-                    It is never necessary to use "+=" together with "_append".
-                    The following sequence of assignments appends "barbaz" to
-                    <filename>FOO</filename>:
-                    <literallayout class='monospaced'>
-     FOO_append = "bar"
-     FOO_append = "baz"
-                    </literallayout>
-                    The only effect of changing the second assignment in the
-                    previous example to use "+=" would be to add a space before
-                    "baz" in the appended value (due to how the "+=" operator
-                    works).
-                </note>
-                Another advantage of the override style operations is that
-                you can combine them with other overrides as described in the
-                "<link linkend='conditional-syntax-overrides'>Conditional Syntax (Overrides)</link>"
-                section.
-            </para>
-        </section>
-
-        <section id='variable-flag-syntax'>
-            <title>Variable Flag Syntax</title>
-
-            <para>
-                Variable flags are BitBake's implementation of variable properties
-                or attributes.
-                It is a way of tagging extra information onto a variable.
-                You can find more out about variable flags in general in the
-                "<link linkend='variable-flags'>Variable Flags</link>"
-                section.
-            </para>
-
-            <para>
-                You can define, append, and prepend values to variable flags.
-                All the standard syntax operations previously mentioned work
-                for variable flags except for override style syntax
-                (i.e. "_prepend", "_append", and "_remove").
-            </para>
-
-            <para>
-                Here are some examples showing how to set variable flags:
-                <literallayout class='monospaced'>
-     FOO[a] = "abc"
-     FOO[b] = "123"
-     FOO[a] += "456"
-                </literallayout>
-                The variable <filename>FOO</filename> has two flags:
-                <filename>[a]</filename> and <filename>[b]</filename>.
-                The flags are immediately set to "abc" and "123", respectively.
-                The <filename>[a]</filename> flag becomes "abc 456".
-            </para>
-
-            <para>
-                No need exists to pre-define variable flags.
-                You can simply start using them.
-                One extremely common application
-                is to attach some brief documentation to a BitBake variable as
-                follows:
-                <literallayout class='monospaced'>
-     CACHE[doc] = "The directory holding the cache of the metadata."
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='inline-python-variable-expansion'>
-            <title>Inline Python Variable Expansion</title>
-
-            <para>
-                You can use inline Python variable expansion to
-                set variables.
-                Here is an example:
-                <literallayout class='monospaced'>
-     DATE = "${@time.strftime('%Y%m%d',time.gmtime())}"
-                </literallayout>
-                This example results in the <filename>DATE</filename>
-                variable being set to the current date.
-            </para>
-
-            <para>
-                Probably the most common use of this feature is to extract
-                the value of variables from BitBake's internal data dictionary,
-                <filename>d</filename>.
-                The following lines select the values of a package name
-                and its version number, respectively:
-                <literallayout class='monospaced'>
-     PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
-     PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
-                </literallayout>
-                <note>
-                    Inline Python expressions work just like variable expansions
-                    insofar as the "=" and ":=" operators are concerned.
-                    Given the following assignment, <filename>foo()</filename>
-                    is called each time <filename>FOO</filename> is expanded:
-                    <literallayout class='monospaced'>
-     FOO = "${@foo()}"
-                    </literallayout>
-                    Contrast this with the following immediate assignment, where
-                    <filename>foo()</filename> is only called once, while the
-                    assignment is parsed:
-                    <literallayout class='monospaced'>
-     FOO := "${@foo()}"
-                    </literallayout>
-                </note>
-                For a different way to set variables with Python code during
-                parsing, see the
-                "<link linkend='anonymous-python-functions'>Anonymous Python Functions</link>"
-                section.
-            </para>
-        </section>
-
-        <section id='unsetting-variables'>
-            <title>Unsetting variables</title>
-
-            <para>
-                It is possible to completely remove a variable or a variable flag
-                from BitBake's internal data dictionary by using the "unset" keyword.
-                Here is an example:
-                <literallayout class='monospaced'>
-        unset DATE
-        unset do_fetch[noexec]
-                </literallayout>
-                These two statements remove the <filename>DATE</filename> and the
-                <filename>do_fetch[noexec]</filename> flag.
-            </para>
-
-        </section>
-
-        <section id='providing-pathnames'>
-            <title>Providing Pathnames</title>
-
-            <para>
-                When specifying pathnames for use with BitBake,
-                do not use the tilde ("~") character as a shortcut
-                for your home directory.
-                Doing so might cause BitBake to not recognize the
-                path since BitBake does not expand this character in
-                the same way a shell would.
-            </para>
-
-            <para>
-                Instead, provide a fuller path as the following
-                example illustrates:
-                <literallayout class='monospaced'>
-     BBLAYERS ?= " \
-       /home/scott-lenovo/LayerA \
-       "
-                </literallayout>
-            </para>
-        </section>
-    </section>
-
-    <section id='exporting-variables-to-the-environment'>
-        <title>Exporting Variables to the Environment</title>
-
-        <para>
-            You can export variables to the environment of running
-            tasks by using the <filename>export</filename> keyword.
-            For example, in the following example, the
-            <filename>do_foo</filename> task prints "value from
-            the environment" when run:
-            <literallayout class='monospaced'>
-     export ENV_VARIABLE
-     ENV_VARIABLE = "value from the environment"
-
-     do_foo() {
-         bbplain "$ENV_VARIABLE"
-     }
-            </literallayout>
-            <note>
-                BitBake does not expand <filename>$ENV_VARIABLE</filename>
-                in this case because it lacks the obligatory
-                <filename>{}</filename>.
-                Rather, <filename>$ENV_VARIABLE</filename> is expanded
-                by the shell.
-            </note>
-            It does not matter whether
-            <filename>export ENV_VARIABLE</filename> appears before or
-            after assignments to <filename>ENV_VARIABLE</filename>.
-        </para>
-
-        <para>
-            It is also possible to combine <filename>export</filename>
-            with setting a value for the variable.
-            Here is an example:
-            <literallayout class='monospaced'>
-     export ENV_VARIABLE = "<replaceable>variable-value</replaceable>"
-            </literallayout>
-            In the output of <filename>bitbake -e</filename>, variables
-            that are exported to the environment are preceded by "export".
-        </para>
-
-        <para>
-            Among the variables commonly exported to the environment
-            are <filename>CC</filename> and <filename>CFLAGS</filename>,
-            which are picked up by many build systems.
-        </para>
-    </section>
-
-    <section id='conditional-syntax-overrides'>
-        <title>Conditional Syntax (Overrides)</title>
-
-        <para>
-            BitBake uses
-            <link linkend='var-bb-OVERRIDES'><filename>OVERRIDES</filename></link>
-            to control what variables are overridden after BitBake
-            parses recipes and configuration files.
-            This section describes how you can use
-            <filename>OVERRIDES</filename> as conditional metadata,
-            talks about key expansion in relationship to
-            <filename>OVERRIDES</filename>, and provides some examples
-            to help with understanding.
-        </para>
-
-        <section id='conditional-metadata'>
-            <title>Conditional Metadata</title>
-
-            <para>
-                You can use <filename>OVERRIDES</filename> to conditionally select
-                a specific version of a variable and to conditionally
-                append or prepend the value of a variable.
-                <note>
-                    Overrides can only use lower-case characters.
-                    Additionally, underscores are not permitted in override names
-                    as they are used to separate overrides from each other and
-                    from the variable name.
-                </note>
-                <itemizedlist>
-                    <listitem><para><emphasis>Selecting a Variable:</emphasis>
-                        The <filename>OVERRIDES</filename> variable is
-                        a colon-character-separated list that contains items
-                        for which you want to satisfy conditions.
-                        Thus, if you have a variable that is conditional on “arm”, and “arm”
-                        is in <filename>OVERRIDES</filename>, then the “arm”-specific
-                        version of the variable is used rather than the non-conditional
-                        version.
-                        Here is an example:
-                        <literallayout class='monospaced'>
-     OVERRIDES = "architecture:os:machine"
-     TEST = "default"
-     TEST_os = "osspecific"
-     TEST_nooverride = "othercondvalue"
-                        </literallayout>
-                        In this example, the <filename>OVERRIDES</filename>
-                        variable lists three overrides:
-                        "architecture", "os", and "machine".
-                        The variable <filename>TEST</filename> by itself has a default
-                        value of "default".
-                        You select the os-specific version of the <filename>TEST</filename>
-                        variable by appending the "os" override to the variable
-                        (i.e.<filename>TEST_os</filename>).
-                        </para>
-
-                        <para>
-                            To better understand this, consider a practical example
-                            that assumes an OpenEmbedded metadata-based Linux
-                            kernel recipe file.
-                            The following lines from the recipe file first set
-                            the kernel branch variable <filename>KBRANCH</filename>
-                            to a default value, then conditionally override that
-                            value based on the architecture of the build:
-                        <literallayout class='monospaced'>
-     KBRANCH = "standard/base"
-     KBRANCH_qemuarm  = "standard/arm-versatile-926ejs"
-     KBRANCH_qemumips = "standard/mti-malta32"
-     KBRANCH_qemuppc  = "standard/qemuppc"
-     KBRANCH_qemux86  = "standard/common-pc/base"
-     KBRANCH_qemux86-64  = "standard/common-pc-64/base"
-     KBRANCH_qemumips64 = "standard/mti-malta64"
-                        </literallayout>
-                        </para></listitem>
-                    <listitem><para><emphasis>Appending and Prepending:</emphasis>
-                        BitBake also supports append and prepend operations to
-                        variable values based on whether a specific item is
-                        listed in <filename>OVERRIDES</filename>.
-                        Here is an example:
-                        <literallayout class='monospaced'>
-     DEPENDS = "glibc ncurses"
-     OVERRIDES = "machine:local"
-     DEPENDS_append_machine = " libmad"
-                        </literallayout>
-                        In this example, <filename>DEPENDS</filename> becomes
-                        "glibc ncurses libmad".
-                        </para>
-
-                        <para>
-                            Again, using an OpenEmbedded metadata-based
-                            kernel recipe file as an example, the
-                            following lines will conditionally append to the
-                            <filename>KERNEL_FEATURES</filename> variable based
-                            on the architecture:
-                        <literallayout class='monospaced'>
-     KERNEL_FEATURES_append = " ${KERNEL_EXTRA_FEATURES}"
-     KERNEL_FEATURES_append_qemux86=" cfg/sound.scc cfg/paravirt_kvm.scc"
-     KERNEL_FEATURES_append_qemux86-64=" cfg/sound.scc cfg/paravirt_kvm.scc"
-                        </literallayout>
-                        </para></listitem>
-                    <listitem><para><emphasis>Setting a Variable for a Single Task:</emphasis>
-                        BitBake supports setting a variable just for the
-                        duration of a single task.
-                        Here is an example:
-                        <literallayout class='monospaced'>
-     FOO_task-configure = "val 1"
-     FOO_task-compile = "val 2"
-                        </literallayout>
-                        In the previous example, <filename>FOO</filename>
-                        has the value "val 1" while the
-                        <filename>do_configure</filename> task is executed,
-                        and the value "val 2" while the
-                        <filename>do_compile</filename> task is executed.
-                        </para>
-
-                        <para>Internally, this is implemented by prepending
-                        the task (e.g. "task-compile:") to the value of
-                        <link linkend='var-bb-OVERRIDES'><filename>OVERRIDES</filename></link>
-                        for the local datastore of the <filename>do_compile</filename>
-                        task.</para>
-
-                        <para>You can also use this syntax with other combinations
-                        (e.g. "<filename>_prepend</filename>") as shown in the
-                        following example:
-                        <literallayout class='monospaced'>
-     EXTRA_OEMAKE_prepend_task-compile = "${PARALLEL_MAKE} "
-                        </literallayout>
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-        </section>
-
-        <section id='key-expansion'>
-            <title>Key Expansion</title>
-
-            <para>
-                Key expansion happens when the BitBake datastore is finalized.
-                To better understand this, consider the following example:
-                <literallayout class='monospaced'>
-     A${B} = "X"
-     B = "2"
-     A2 = "Y"
-                </literallayout>
-                In this case, after all the parsing is complete,
-                BitBake expands <filename>${B}</filename> into "2".
-                This expansion causes <filename>A2</filename>, which was
-                set to "Y" before the expansion, to become "X".
-            </para>
-        </section>
-
-        <section id='variable-interaction-worked-examples'>
-            <title>Examples</title>
-
-            <para>
-                Despite the previous explanations that show the different forms of
-                variable definitions, it can be hard to work
-                out exactly what happens when variable operators, conditional
-                overrides, and unconditional overrides are combined.
-                This section presents some common scenarios along
-                with explanations for variable interactions that
-                typically confuse users.
-            </para>
-
-            <para>
-                There is often confusion concerning the order in which
-                overrides and various "append" operators take effect.
-                Recall that an append or prepend operation using "_append"
-                and "_prepend" does not result in an immediate assignment
-                as would "+=", ".=", "=+", or "=.".
-                Consider the following example:
-                <literallayout class='monospaced'>
-     OVERRIDES = "foo"
-     A = "Z"
-     A_foo_append = "X"
-                </literallayout>
-                For this case, <filename>A</filename> is
-                unconditionally set to "Z" and "X" is
-                unconditionally and immediately appended to the variable
-                <filename>A_foo</filename>.
-                Because overrides have not been applied yet,
-                <filename>A_foo</filename> is set to "X" due to the append
-                and <filename>A</filename> simply equals "Z".
-            </para>
-
-            <para>
-                Applying overrides, however, changes things.
-                Since "foo" is listed in <filename>OVERRIDES</filename>,
-                the conditional variable <filename>A</filename> is replaced
-                with the "foo" version, which is equal to "X".
-                So effectively, <filename>A_foo</filename> replaces <filename>A</filename>.
-            </para>
-
-            <para>
-                This next example changes the order of the override and
-                the append:
-                <literallayout class='monospaced'>
-     OVERRIDES = "foo"
-     A = "Z"
-     A_append_foo = "X"
-                </literallayout>
-                For this case, before overrides are handled,
-                <filename>A</filename> is set to "Z" and <filename>A_append_foo</filename>
-                is set to "X".
-                Once the override for "foo" is applied, however,
-                <filename>A</filename> gets appended with "X".
-                Consequently, <filename>A</filename> becomes "ZX".
-                Notice that spaces are not appended.
-            </para>
-
-            <para>
-                This next example has the order of the appends and overrides reversed
-                back as in the first example:
-                <literallayout class='monospaced'>
-     OVERRIDES = "foo"
-     A = "Y"
-     A_foo_append = "Z"
-     A_foo_append = "X"
-                </literallayout>
-                For this case, before any overrides are resolved,
-                <filename>A</filename> is set to "Y" using an immediate assignment.
-                After this immediate assignment, <filename>A_foo</filename> is set
-                to "Z", and then further appended with
-                "X" leaving the variable set to "ZX".
-                Finally, applying the override for "foo" results in the conditional
-                variable <filename>A</filename> becoming "ZX" (i.e.
-                <filename>A</filename> is replaced with <filename>A_foo</filename>).
-            </para>
-
-            <para>
-                This final example mixes in some varying operators:
-                <literallayout class='monospaced'>
-     A = "1"
-     A_append = "2"
-     A_append = "3"
-     A += "4"
-     A .= "5"
-                </literallayout>
-                For this case, the type of append operators are affecting the
-                order of assignments as BitBake passes through the code
-                multiple times.
-                Initially, <filename>A</filename> is set to "1 45" because
-                of the three statements that use immediate operators.
-                After these assignments are made, BitBake applies the
-                "_append" operations.
-                Those operations result in <filename>A</filename> becoming "1 4523".
-            </para>
-        </section>
-    </section>
-
-    <section id='sharing-functionality'>
-        <title>Sharing Functionality</title>
-
-        <para>
-            BitBake allows for metadata sharing through include files
-            (<filename>.inc</filename>) and class files
-            (<filename>.bbclass</filename>).
-            For example, suppose you have a piece of common functionality
-            such as a task definition that you want to share between
-            more than one recipe.
-            In this case, creating a <filename>.bbclass</filename>
-            file that contains the common functionality and then using
-            the <filename>inherit</filename> directive in your recipes to
-            inherit the class would be a common way to share the task.
-        </para>
-
-        <para>
-            This section presents the mechanisms BitBake provides to
-            allow you to share functionality between recipes.
-            Specifically, the mechanisms include <filename>include</filename>,
-            <filename>inherit</filename>, <filename>INHERIT</filename>, and
-            <filename>require</filename> directives.
-        </para>
-
-        <section id='locating-include-and-class-files'>
-            <title>Locating Include and Class Files</title>
-
-            <para>
-                BitBake uses the
-                <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
-                variable to locate needed include and class files.
-                Additionally, BitBake searches the current directory for
-                <filename>include</filename> and <filename>require</filename>
-                directives.
-                <note>
-                    The <filename>BBPATH</filename> variable is analogous to
-                    the environment variable <filename>PATH</filename>.
-                </note>
-            </para>
-
-            <para>
-                In order for include and class files to be found by BitBake,
-                they need to be located in a "classes" subdirectory that can
-                be found in <filename>BBPATH</filename>.
-            </para>
-        </section>
-
-        <section id='inherit-directive'>
-            <title><filename>inherit</filename> Directive</title>
-
-            <para>
-                When writing a recipe or class file, you can use the
-                <filename>inherit</filename> directive to inherit the
-                functionality of a class (<filename>.bbclass</filename>).
-                BitBake only supports this directive when used within recipe
-                and class files (i.e. <filename>.bb</filename> and
-                <filename>.bbclass</filename>).
-            </para>
-
-            <para>
-                The <filename>inherit</filename> directive is a rudimentary
-                means of specifying functionality contained in class files
-                that your recipes require.
-                For example, you can easily abstract out the tasks involved in
-                building a package that uses Autoconf and Automake and put
-                those tasks into a class file and then have your recipe
-                inherit that class file.
-            </para>
-
-            <para>
-                As an example, your recipes could use the following directive
-                to inherit an <filename>autotools.bbclass</filename> file.
-                The class file would contain common functionality for using
-                Autotools that could be shared across recipes:
-                <literallayout class='monospaced'>
-     inherit autotools
-                </literallayout>
-                In this case, BitBake would search for the directory
-                <filename>classes/autotools.bbclass</filename>
-                in <filename>BBPATH</filename>.
-                <note>
-                    You can override any values and functions of the
-                    inherited class within your recipe by doing so
-                    after the "inherit" statement.
-                </note>
-                If you want to use the directive to inherit
-                multiple classes, separate them with spaces.
-                The following example shows how to inherit both the
-                <filename>buildhistory</filename> and <filename>rm_work</filename>
-                classes:
-                <literallayout class='monospaced'>
-     inherit buildhistory rm_work
-                </literallayout>
-            </para>
-
-            <para>
-                An advantage with the inherit directive as compared to both
-                the
-                <link linkend='include-directive'>include</link> and
-                <link linkend='require-inclusion'>require</link> directives
-                is that you can inherit class files conditionally.
-                You can accomplish this by using a variable expression
-                after the <filename>inherit</filename> statement.
-                Here is an example:
-                <literallayout class='monospaced'>
-     inherit ${VARNAME}
-                </literallayout>
-                If <filename>VARNAME</filename> is going to be set, it needs
-                to be set before the <filename>inherit</filename> statement
-                is parsed.
-                One way to achieve a conditional inherit in this case is to use
-                overrides:
-                <literallayout class='monospaced'>
-     VARIABLE = ""
-     VARIABLE_someoverride = "myclass"
-                </literallayout>
-            </para>
-
-            <para>
-                Another method is by using anonymous Python.
-                Here is an example:
-                <literallayout class='monospaced'>
-     python () {
-         if condition == value:
-             d.setVar('VARIABLE', 'myclass')
-         else:
-             d.setVar('VARIABLE', '')
-     }
-                </literallayout>
-            </para>
-
-            <para>
-                Alternatively, you could use an in-line Python expression
-                in the following form:
-                <literallayout class='monospaced'>
-     inherit ${@'classname' if condition else ''}
-     inherit ${@functionname(params)}
-                </literallayout>
-                In all cases, if the expression evaluates to an empty
-                string, the statement does not trigger a syntax error
-                because it becomes a no-op.
-            </para>
-        </section>
-
-        <section id='include-directive'>
-            <title><filename>include</filename> Directive</title>
-
-            <para>
-                BitBake understands the <filename>include</filename>
-                directive.
-                This directive causes BitBake to parse whatever file you specify,
-                and to insert that file at that location.
-                The directive is much like its equivalent in Make except
-                that if the path specified on the include line is a relative
-                path, BitBake locates the first file it can find
-                within <filename>BBPATH</filename>.
-            </para>
-
-            <para>
-                The include directive is a more generic method of including
-                functionality as compared to the
-                <link linkend='inherit-directive'>inherit</link> directive,
-                which is restricted to class (i.e. <filename>.bbclass</filename>)
-                files.
-                The include directive is applicable for any other kind of
-                shared or encapsulated functionality or configuration that
-                does not suit a <filename>.bbclass</filename> file.
-            </para>
-
-            <para>
-                As an example, suppose you needed a recipe to include some
-                self-test definitions:
-                <literallayout class='monospaced'>
-     include test_defs.inc
-                </literallayout>
-                <note>
-                    The <filename>include</filename> directive does not
-                    produce an error when the file cannot be found.
-                    Consequently, it is recommended that if the file you
-                    are including is expected to exist, you should use
-                    <link linkend='require-inclusion'><filename>require</filename></link>
-                    instead of <filename>include</filename>.
-                    Doing so makes sure that an error is produced if the
-                    file cannot be found.
-                </note>
-            </para>
-        </section>
-
-        <section id='require-inclusion'>
-            <title><filename>require</filename> Directive</title>
-
-            <para>
-                BitBake understands the <filename>require</filename>
-                directive.
-                This directive behaves just like the
-                <filename>include</filename> directive with the exception that
-                BitBake raises a parsing error if the file to be included cannot
-                be found.
-                Thus, any file you require is inserted into the file that is
-                being parsed at the location of the directive.
-            </para>
-
-            <para>
-                The require directive, like the include directive previously
-                described, is a more generic method of including
-                functionality as compared to the
-                <link linkend='inherit-directive'>inherit</link> directive,
-                which is restricted to class (i.e. <filename>.bbclass</filename>)
-                files.
-                The require directive is applicable for any other kind of
-                shared or encapsulated functionality or configuration that
-                does not suit a <filename>.bbclass</filename> file.
-            </para>
-
-            <para>
-                Similar to how BitBake handles
-                <link linkend='include-directive'><filename>include</filename></link>,
-                if the path specified
-                on the require line is a relative path, BitBake locates
-                the first file it can find within <filename>BBPATH</filename>.
-            </para>
-
-            <para>
-                As an example, suppose you have two versions of a recipe
-                (e.g. <filename>foo_1.2.2.bb</filename> and
-                <filename>foo_2.0.0.bb</filename>) where
-                each version contains some identical functionality that could be
-                shared.
-                You could create an include file named <filename>foo.inc</filename>
-                that contains the common definitions needed to build "foo".
-                You need to be sure <filename>foo.inc</filename> is located in the
-                same directory as your two recipe files as well.
-                Once these conditions are set up, you can share the functionality
-                using a <filename>require</filename> directive from within each
-                recipe:
-                <literallayout class='monospaced'>
-     require foo.inc
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='inherit-configuration-directive'>
-            <title><filename>INHERIT</filename> Configuration Directive</title>
-
-            <para>
-                When creating a configuration file (<filename>.conf</filename>),
-                you can use the
-                <link linkend='var-bb-INHERIT'><filename>INHERIT</filename></link>
-                configuration directive to inherit a class.
-                BitBake only supports this directive when used within
-                a configuration file.
-            </para>
-
-            <para>
-                As an example, suppose you needed to inherit a class
-                file called <filename>abc.bbclass</filename> from a
-                configuration file as follows:
-                <literallayout class='monospaced'>
-     INHERIT += "abc"
-                </literallayout>
-                This configuration directive causes the named
-                class to be inherited at the point of the directive
-                during parsing.
-                As with the <filename>inherit</filename> directive, the
-                <filename>.bbclass</filename> file must be located in a
-                "classes" subdirectory in one of the directories specified
-                in <filename>BBPATH</filename>.
-                <note>
-                    Because <filename>.conf</filename> files are parsed
-                    first during BitBake's execution, using
-                    <filename>INHERIT</filename> to inherit a class effectively
-                    inherits the class globally (i.e. for all recipes).
-                </note>
-                If you want to use the directive to inherit
-                multiple classes, you can provide them on the same line in the
-                <filename>local.conf</filename> file.
-                Use spaces to separate the classes.
-                The following example shows how to inherit both the
-                <filename>autotools</filename> and <filename>pkgconfig</filename>
-                classes:
-                <literallayout class='monospaced'>
-     INHERIT += "autotools pkgconfig"
-                </literallayout>
-            </para>
-        </section>
-    </section>
-
-    <section id='functions'>
-        <title>Functions</title>
-
-        <para>
-            As with most languages, functions are the building blocks that
-            are used to build up operations into tasks.
-            BitBake supports these types of functions:
-            <itemizedlist>
-                <listitem><para><emphasis>Shell Functions:</emphasis>
-                    Functions written in shell script and executed either
-                    directly as functions, tasks, or both.
-                    They can also be called by other shell functions.
-                    </para></listitem>
-                <listitem><para><emphasis>BitBake-Style Python Functions:</emphasis>
-                    Functions written in Python and executed by BitBake or other
-                    Python functions using <filename>bb.build.exec_func()</filename>.
-                    </para></listitem>
-                <listitem><para><emphasis>Python Functions:</emphasis>
-                    Functions written in Python and executed by Python.
-                    </para></listitem>
-                <listitem><para><emphasis>Anonymous Python Functions:</emphasis>
-                    Python functions executed automatically during
-                    parsing.
-                    </para></listitem>
-            </itemizedlist>
-            Regardless of the type of function, you can only
-            define them in class (<filename>.bbclass</filename>)
-            and recipe (<filename>.bb</filename> or <filename>.inc</filename>)
-            files.
-        </para>
-
-        <section id='shell-functions'>
-            <title>Shell Functions</title>
-
-            <para>
-                Functions written in shell script and executed either
-                directly as functions, tasks, or both.
-                They can also be called by other shell functions.
-                Here is an example shell function definition:
-                <literallayout class='monospaced'>
-     some_function () {
-         echo "Hello World"
-     }
-                </literallayout>
-                When you create these types of functions in your recipe
-                or class files, you need to follow the shell programming
-                rules.
-                The scripts are executed by <filename>/bin/sh</filename>,
-                which may not be a bash shell but might be something
-                such as <filename>dash</filename>.
-                You should not use Bash-specific script (bashisms).
-            </para>
-
-            <para>
-                Overrides and override-style operators like
-                <filename>_append</filename> and
-                <filename>_prepend</filename> can also be applied to
-                shell functions.
-                Most commonly, this application would be used in a
-                <filename>.bbappend</filename> file to modify functions in
-                the main recipe.
-                It can also be used to modify functions inherited from
-                classes.
-            </para>
-
-            <para>
-                As an example, consider the following:
-                <literallayout class='monospaced'>
-     do_foo() {
-         bbplain first
-         fn
-     }
-
-     fn_prepend() {
-         bbplain second
-     }
-
-     fn() {
-         bbplain third
-     }
-
-     do_foo_append() {
-         bbplain fourth
-     }
-                </literallayout>
-                Running <filename>do_foo</filename>
-                prints the following:
-                <literallayout class='monospaced'>
-     recipename do_foo: first
-     recipename do_foo: second
-     recipename do_foo: third
-     recipename do_foo: fourth
-                </literallayout>
-                <note>
-                    Overrides and override-style operators can
-                    be applied to any shell function, not just
-                    <link linkend='tasks'>tasks</link>.
-                </note>
-                You can use the <filename>bitbake -e</filename>&nbsp;<replaceable>recipename</replaceable>
-                command to view the final assembled function
-                after all overrides have been applied.
-            </para>
-        </section>
-
-        <section id='bitbake-style-python-functions'>
-            <title>BitBake-Style Python Functions</title>
-
-            <para>
-                These functions are written in Python and executed by
-                BitBake or other Python functions using
-                <filename>bb.build.exec_func()</filename>.
-            </para>
-
-            <para>
-                An example BitBake function is:
-                <literallayout class='monospaced'>
-     python some_python_function () {
-         d.setVar("TEXT", "Hello World")
-         print d.getVar("TEXT")
-     }
-                </literallayout>
-                Because the Python "bb" and "os" modules are already
-                imported, you do not need to import these modules.
-                Also in these types of functions, the datastore ("d")
-                is a global variable and is always automatically
-                available.
-                <note>
-                    Variable expressions (e.g. <filename>${X}</filename>)
-                    are no longer expanded within Python functions.
-                    This behavior is intentional in order to allow you
-                    to freely set variable values to expandable expressions
-                    without having them expanded prematurely.
-                    If you do wish to expand a variable within a Python
-                    function, use <filename>d.getVar("X")</filename>.
-                    Or, for more complicated expressions, use
-                    <filename>d.expand()</filename>.
-                </note>
-            </para>
-
-            <para>
-                Similar to shell functions, you can also apply overrides
-                and override-style operators to BitBake-style Python
-                functions.
-            </para>
-
-            <para>
-                As an example, consider the following:
-                <literallayout class='monospaced'>
-     python do_foo_prepend() {
-         bb.plain("first")
-     }
-
-     python do_foo() {
-         bb.plain("second")
-     }
-
-     python do_foo_append() {
-         bb.plain("third")
-     }
-                </literallayout>
-                Running <filename>do_foo</filename> prints
-                the following:
-                <literallayout class='monospaced'>
-     recipename do_foo: first
-     recipename do_foo: second
-     recipename do_foo: third
-                </literallayout>
-                You can use the <filename>bitbake -e</filename>&nbsp;<replaceable>recipename</replaceable>
-                command to view the final assembled function
-                after all overrides have been applied.
-            </para>
-        </section>
-
-        <section id='python-functions'>
-            <title>Python Functions</title>
-
-            <para>
-                These functions are written in Python and are executed by
-                other Python code.
-                Examples of Python functions are utility functions
-                that you intend to call from in-line Python or
-                from within other Python functions.
-                Here is an example:
-                <literallayout class='monospaced'>
-     def get_depends(d):
-         if d.getVar('SOMECONDITION'):
-             return "dependencywithcond"
-         else:
-             return "dependency"
-     SOMECONDITION = "1"
-     DEPENDS = "${@get_depends(d)}"
-                </literallayout>
-                This would result in <filename>DEPENDS</filename>
-                containing <filename>dependencywithcond</filename>.
-            </para>
-
-            <para>
-                Here are some things to know about Python functions:
-                <itemizedlist>
-                    <listitem><para>Python functions can take parameters.
-                        </para></listitem>
-                    <listitem><para>The BitBake datastore is not
-                        automatically available.
-                        Consequently, you must pass it in as a
-                        parameter to the function.
-                        </para></listitem>
-                    <listitem><para>The "bb" and "os" Python modules are
-                        automatically available.
-                        You do not need to import them.
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-        </section>
-
-        <section id='bitbake-style-python-functions-versus-python-functions'>
-            <title>BitBake-Style Python Functions Versus Python Functions</title>
-
-            <para>
-                Following are some important differences between
-                BitBake-style Python functions and regular Python
-                functions defined with "def":
-                <itemizedlist>
-                    <listitem><para>
-                        Only BitBake-style Python functions can be
-                        <link linkend='tasks'>tasks</link>.
-                        </para></listitem>
-                    <listitem><para>
-                        Overrides and override-style operators can only
-                        be applied to BitBake-style Python functions.
-                        </para></listitem>
-                    <listitem><para>
-                        Only regular Python functions can take arguments
-                        and return values.
-                        </para></listitem>
-                    <listitem><para>
-                        <link linkend='variable-flags'>Variable flags</link>
-                        such as <filename>[dirs]</filename>,
-                        <filename>[cleandirs]</filename>, and
-                        <filename>[lockfiles]</filename> can be used
-                        on BitBake-style Python functions, but not on
-                        regular Python functions.
-                        </para></listitem>
-                    <listitem><para>
-                        BitBake-style Python functions generate a separate
-                        <filename>${</filename><link linkend='var-bb-T'><filename>T</filename></link><filename>}/run.</filename><replaceable>function-name</replaceable><filename>.</filename><replaceable>pid</replaceable>
-                        script that is executed to run the function, and also
-                        generate a log file in
-                        <filename>${T}/log.</filename><replaceable>function-name</replaceable><filename>.</filename><replaceable>pid</replaceable>
-                        if they are executed as tasks.</para>
-
-                        <para>
-                        Regular Python functions execute "inline" and do not
-                        generate any files in <filename>${T}</filename>.
-                        </para></listitem>
-                    <listitem><para>
-                        Regular Python functions are called with the usual
-                        Python syntax.
-                        BitBake-style Python functions are usually tasks and
-                        are called directly by BitBake, but can also be called
-                        manually from Python code by using the
-                        <filename>bb.build.exec_func()</filename> function.
-                        Here is an example:
-                        <literallayout class='monospaced'>
-     bb.build.exec_func("my_bitbake_style_function", d)
-                        </literallayout>
-                        <note>
-                            <filename>bb.build.exec_func()</filename> can also
-                            be used to run shell functions from Python code.
-                            If you want to run a shell function before a Python
-                            function within the same task, then you can use a
-                            parent helper Python function that starts by running
-                            the shell function with
-                            <filename>bb.build.exec_func()</filename> and then
-                            runs the Python code.
-                        </note></para>
-
-                        <para>To detect errors from functions executed with
-                        <filename>bb.build.exec_func()</filename>, you
-                        can catch the <filename>bb.build.FuncFailed</filename>
-                        exception.
-                        <note>
-                            Functions in metadata (recipes and classes) should
-                            not themselves raise
-                            <filename>bb.build.FuncFailed</filename>.
-                            Rather, <filename>bb.build.FuncFailed</filename>
-                            should be viewed as a general indicator that the
-                            called function failed by raising an exception.
-                            For example, an exception raised by
-                            <filename>bb.fatal()</filename> will be caught inside
-                            <filename>bb.build.exec_func()</filename>, and a
-                            <filename>bb.build.FuncFailed</filename> will be raised
-                            in response.
-                        </note>
-                        </para></listitem>
-                </itemizedlist>
-            </para>
-
-            <para>
-                Due to their simplicity, you should prefer regular Python functions
-                over BitBake-style Python functions unless you need a feature specific
-                to BitBake-style Python functions.
-                Regular Python functions in metadata are a more recent invention than
-                BitBake-style Python functions, and older code tends to use
-                <filename>bb.build.exec_func()</filename> more often.
-            </para>
-        </section>
-
-        <section id='anonymous-python-functions'>
-            <title>Anonymous Python Functions</title>
-
-            <para>
-                Sometimes it is useful to set variables or perform
-                other operations programmatically during parsing.
-                To do this, you can define special Python functions,
-                called anonymous Python functions, that run at the
-                end of parsing.
-                For example, the following conditionally sets a variable
-                based on the value of  another variable:
-                <literallayout class='monospaced'>
-     python () {
-         if d.getVar('SOMEVAR') == 'value':
-             d.setVar('ANOTHERVAR', 'value2')
-     }
-                </literallayout>
-                An equivalent way to mark a function as an anonymous
-                function is to give it the name "__anonymous", rather
-                than no name.
-            </para>
-
-            <para>
-                Anonymous Python functions always run at the end
-                of parsing, regardless of where they are defined.
-                If a recipe contains many anonymous functions, they
-                run in the same order as they are defined within the
-                recipe.
-                As an example, consider the following snippet:
-                <literallayout class='monospaced'>
-     python () {
-         d.setVar('FOO', 'foo 2')
-     }
-
-     FOO = "foo 1"
-
-     python () {
-         d.appendVar('BAR', ' bar 2')
-     }
-
-     BAR = "bar 1"
-                </literallayout>
-                The previous example is conceptually equivalent to the
-                following snippet:
-                <literallayout class='monospaced'>
-     FOO = "foo 1"
-     BAR = "bar 1"
-     FOO = "foo 2"
-     BAR += "bar 2"
-                </literallayout>
-                <filename>FOO</filename> ends up with the value "foo 2",
-                and <filename>BAR</filename> with the value "bar 1 bar 2".
-                Just as in the second snippet, the values set for the
-                variables within the anonymous functions become available
-                to tasks, which always run after parsing.
-            </para>
-
-            <para>
-                Overrides and override-style operators such as
-                "<filename>_append</filename>" are applied before
-                anonymous functions run.
-                In the following example, <filename>FOO</filename> ends
-                up with the value "foo from anonymous":
-                <literallayout class='monospaced'>
-     FOO = "foo"
-     FOO_append = " from outside"
-
-     python () {
-         d.setVar("FOO", "foo from anonymous")
-     }
-                </literallayout>
-                For methods you can use with anonymous Python functions,
-                see the
-                "<link linkend='functions-you-can-call-from-within-python'>Functions You Can Call From Within Python</link>"
-                section.
-                For a different method to run Python code during parsing,
-                see the
-                "<link linkend='inline-python-variable-expansion'>Inline Python Variable Expansion</link>"
-                section.
-            </para>
-        </section>
-
-        <section id='flexible-inheritance-for-class-functions'>
-            <title>Flexible Inheritance for Class Functions</title>
-
-            <para>
-                Through coding techniques and the use of
-                <filename>EXPORT_FUNCTIONS</filename>, BitBake supports
-                exporting a function from a class such that the
-                class function appears as the default implementation
-                of the function, but can still be called if a recipe
-                inheriting the class needs to define its own version of
-                the function.
-            </para>
-
-            <para>
-                To understand the benefits of this feature, consider
-                the basic scenario where a class defines a task function
-                and your recipe inherits the class.
-                In this basic scenario, your recipe inherits the task
-                function as defined in the class.
-                If desired, your recipe can add to the start and end of the
-                function by using the "_prepend" or "_append" operations
-                respectively, or it can redefine the function completely.
-                However, if it redefines the function, there is
-                no means  for it to call the class version of the function.
-                <filename>EXPORT_FUNCTIONS</filename> provides a mechanism
-                that enables the recipe's version of the function to call
-                the original version of the function.
-            </para>
-
-            <para>
-                To make use of this technique, you need the following
-                things in place:
-                <itemizedlist>
-                    <listitem><para>
-                        The class needs to define the function as follows:
-                        <literallayout class='monospaced'>
-     <replaceable>classname</replaceable><filename>_</filename><replaceable>functionname</replaceable>
-                        </literallayout>
-                        For example, if you have a class file
-                        <filename>bar.bbclass</filename> and a function named
-                        <filename>do_foo</filename>, the class must define the function
-                        as follows:
-                        <literallayout class='monospaced'>
-     bar_do_foo
-                        </literallayout>
-                        </para></listitem>
-                    <listitem><para>
-                        The class needs to contain the <filename>EXPORT_FUNCTIONS</filename>
-                        statement as follows:
-                        <literallayout class='monospaced'>
-     EXPORT_FUNCTIONS <replaceable>functionname</replaceable>
-                        </literallayout>
-                        For example, continuing with the same example, the
-                        statement in the <filename>bar.bbclass</filename> would be
-                        as follows:
-                        <literallayout class='monospaced'>
-     EXPORT_FUNCTIONS do_foo
-                        </literallayout>
-                        </para></listitem>
-                    <listitem><para>
-                        You need to call the function appropriately from within your
-                        recipe.
-                        Continuing with the same example, if your recipe
-                        needs to call the class version of the function,
-                        it should call <filename>bar_do_foo</filename>.
-                        Assuming <filename>do_foo</filename> was a shell function
-                        and <filename>EXPORT_FUNCTIONS</filename> was used as above,
-                        the recipe's function could conditionally call the
-                        class version of the function as follows:
-                        <literallayout class='monospaced'>
-     do_foo() {
-             if [ somecondition ] ; then
-                     bar_do_foo
-             else
-                     # Do something else
-             fi
-     }
-                        </literallayout>
-                        To call your modified version of the function as defined
-                        in your recipe, call it as <filename>do_foo</filename>.
-                        </para></listitem>
-                </itemizedlist>
-                With these conditions met, your single recipe
-                can freely choose between the original function
-                as defined in the class file and the modified function in your recipe.
-                If you do not set up these conditions, you are limited to using one function
-                or the other.
-            </para>
-        </section>
-    </section>
-
-    <section id='tasks'>
-        <title>Tasks</title>
-
-        <para>
-            Tasks are BitBake execution units that make up the
-            steps that BitBake can run for a given recipe.
-            Tasks are only supported in recipes and classes
-            (i.e. in <filename>.bb</filename> files and files
-            included or inherited from <filename>.bb</filename>
-            files).
-            By convention, tasks have names that start with "do_".
-        </para>
-
-        <section id='promoting-a-function-to-a-task'>
-            <title>Promoting a Function to a Task</title>
-
-            <para>
-                Tasks are either
-                <link linkend='shell-functions'>shell functions</link> or
-                <link linkend='bitbake-style-python-functions'>BitBake-style Python functions</link>
-                that have been promoted to tasks by using the
-                <filename>addtask</filename> command.
-                The <filename>addtask</filename> command can also
-                optionally describe dependencies between the
-                task and other tasks.
-                Here is an example that shows how to define a task
-                and declare some dependencies:
-                <literallayout class='monospaced'>
-     python do_printdate () {
-         import time
-         print time.strftime('%Y%m%d', time.gmtime())
-     }
-     addtask printdate after do_fetch before do_build
-                </literallayout>
-                The first argument to <filename>addtask</filename>
-                is the name of the function to promote to
-                a task.
-                If the name does not start with "do_", "do_" is
-                implicitly added, which enforces the convention that
-                all task names start with "do_".
-            </para>
-
-            <para>
-                In the previous example, the
-                <filename>do_printdate</filename> task becomes a
-                dependency of the <filename>do_build</filename>
-                task, which is the default task (i.e. the task run by
-                the <filename>bitbake</filename> command unless
-                another task is specified explicitly).
-                Additionally, the <filename>do_printdate</filename>
-                task becomes dependent upon the
-                <filename>do_fetch</filename> task.
-                Running the <filename>do_build</filename> task
-                results in the <filename>do_printdate</filename>
-                task running first.
-                <note>
-                    If you try out the previous example, you might see that
-                    the <filename>do_printdate</filename> task is only run
-                    the first time you build the recipe with
-                    the <filename>bitbake</filename> command.
-                    This is because BitBake considers the task "up-to-date"
-                    after that initial run.
-                    If you want to force the task to always be rerun for
-                    experimentation purposes, you can make BitBake always
-                    consider the task "out-of-date" by using the
-                    <filename>[</filename><link linkend='variable-flags'><filename>nostamp</filename></link><filename>]</filename>
-                    variable flag, as follows:
-                    <literallayout class='monospaced'>
-     do_printdate[nostamp] = "1"
-                    </literallayout>
-                    You can also explicitly run the task and provide the
-                    <filename>-f</filename> option as follows:
-                    <literallayout class='monospaced'>
-     $ bitbake <replaceable>recipe</replaceable> -c printdate -f
-                    </literallayout>
-                    When manually selecting a task to run with the
-                    <filename>bitbake</filename>&nbsp;<replaceable>recipe</replaceable>&nbsp;<filename>-c</filename>&nbsp;<replaceable>task</replaceable>
-                    command, you can omit the "do_" prefix as part of the
-                    task name.
-                </note>
-            </para>
-
-            <para>
-                You might wonder about the practical effects of using
-                <filename>addtask</filename> without specifying any
-                dependencies as is done in the following example:
-                <literallayout class='monospaced'>
-     addtask printdate
-                </literallayout>
-                In this example, assuming dependencies have not been
-                added through some other means, the only way to run
-                the task is by explicitly selecting it with
-                <filename>bitbake</filename>&nbsp;<replaceable>recipe</replaceable>&nbsp;<filename>-c printdate</filename>.
-                You can use the
-                <filename>do_listtasks</filename> task to list all tasks
-                defined in a recipe as shown in the following example:
-                <literallayout class='monospaced'>
-     $ bitbake <replaceable>recipe</replaceable> -c listtasks
-                </literallayout>
-                For more information on task dependencies, see the
-                "<link linkend='dependencies'>Dependencies</link>"
-                section.
-            </para>
-
-            <para>
-                See the
-                "<link linkend='variable-flags'>Variable Flags</link>"
-                section for information on variable flags you can use with
-                tasks.
-            </para>
-        </section>
-
-        <section id='deleting-a-task'>
-            <title>Deleting a Task</title>
-
-            <para>
-                As well as being able to add tasks, you can delete them.
-                Simply use the <filename>deltask</filename> command to
-                delete a task.
-                For example, to delete the example task used in the previous
-                sections, you would use:
-                <literallayout class='monospaced'>
-     deltask printdate
-                </literallayout>
-                If you delete a task using the <filename>deltask</filename>
-                command and the task has dependencies, the dependencies are
-                not reconnected.
-                For example, suppose you have three tasks named
-                <filename>do_a</filename>, <filename>do_b</filename>, and
-                <filename>do_c</filename>.
-                Furthermore, <filename>do_c</filename> is dependent on
-                <filename>do_b</filename>, which in turn is dependent on
-                <filename>do_a</filename>.
-                Given this scenario, if you use <filename>deltask</filename>
-                to delete <filename>do_b</filename>, the implicit dependency
-                relationship between <filename>do_c</filename> and
-                <filename>do_a</filename> through <filename>do_b</filename>
-                no longer exists, and <filename>do_c</filename> dependencies
-                are not updated to include <filename>do_a</filename>.
-                Thus, <filename>do_c</filename> is free to run before
-                <filename>do_a</filename>.
-            </para>
-
-            <para>
-                If you want dependencies such as these to remain intact, use
-                the <filename>[noexec]</filename> varflag to disable the task
-                instead of using the <filename>deltask</filename> command to
-                delete it:
-                <literallayout class='monospaced'>
-     do_b[noexec] = "1"
-                </literallayout>
-            </para>
-        </section>
-
-        <section id='passing-information-into-the-build-task-environment'>
-            <title>Passing Information Into the Build Task Environment</title>
-
-            <para>
-                When running a task, BitBake tightly controls the shell execution
-                environment of the build tasks to make
-                sure unwanted contamination from the build machine cannot
-                influence the build.
-                <note>
-                    By default, BitBake cleans the environment to include only those
-                    things exported or listed in its whitelist to ensure that the build
-                    environment is reproducible and consistent.
-                    You can prevent this "cleaning" by setting the
-                    <link linkend='var-bb-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>
-                    variable.
-                </note>
-                Consequently, if you do want something to get passed into the
-                build task environment, you must take these two steps:
-                <orderedlist>
-                    <listitem><para>
-                        Tell BitBake to load what you want from the environment
-                        into the datastore.
-                        You can do so through the
-                        <link linkend='var-bb-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>
-                        and
-                        <link linkend='var-bb-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>
-                        variables.
-                        For example, assume you want to prevent the build system from
-                        accessing your <filename>$HOME/.ccache</filename>
-                        directory.
-                        The following command "whitelists" the environment variable
-                        <filename>CCACHE_DIR</filename> causing BitBake to allow that
-                        variable into the datastore:
-                        <literallayout class='monospaced'>
-     export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"
-                        </literallayout></para></listitem>
-                    <listitem><para>
-                        Tell BitBake to export what you have loaded into the
-                        datastore to the task environment of every running task.
-                        Loading something from the environment into the datastore
-                        (previous step) only makes it available in the datastore.
-                        To export it to the task environment of every running task,
-                        use a command similar to the following in your local configuration
-                        file <filename>local.conf</filename> or your
-                        distribution configuration file:
-                        <literallayout class='monospaced'>
-     export CCACHE_DIR
-                        </literallayout>
-                        <note>
-                            A side effect of the previous steps is that BitBake
-                            records the variable as a dependency of the build process
-                            in things like the setscene checksums.
-                            If doing so results in unnecessary rebuilds of tasks, you can
-                            whitelist the variable so that the setscene code
-                            ignores the dependency when it creates checksums.
-                        </note></para></listitem>
-                </orderedlist>
-            </para>
-
-            <para>
-                Sometimes, it is useful to be able to obtain information
-                from the original execution environment.
-                BitBake saves a copy of the original environment into
-                a special variable named
-                <link linkend='var-bb-BB_ORIGENV'><filename>BB_ORIGENV</filename></link>.
-            </para>
-
-            <para>
-                The <filename>BB_ORIGENV</filename> variable returns a datastore
-                object that can be queried using the standard datastore operators
-                such as <filename>getVar(, False)</filename>.
-                The datastore object is useful, for example, to find the original
-                <filename>DISPLAY</filename> variable.
-                Here is an example:
-                <literallayout class='monospaced'>
-     origenv = d.getVar("BB_ORIGENV", False)
-     bar = origenv.getVar("BAR", False)
-                </literallayout>
-                The previous example returns <filename>BAR</filename> from the original
-                execution environment.
-            </para>
-        </section>
-    </section>
-
-    <section id='variable-flags'>
-        <title>Variable Flags</title>
-
-        <para>
-            Variable flags (varflags) help control a task's functionality
-            and dependencies.
-            BitBake reads and writes varflags to the datastore using the following
-            command forms:
-            <literallayout class='monospaced'>
-     <replaceable>variable</replaceable> = d.getVarFlags("<replaceable>variable</replaceable>")
-     self.d.setVarFlags("FOO", {"func": True})
-            </literallayout>
-        </para>
-
-        <para>
-            When working with varflags, the same syntax, with the exception of
-            overrides, applies.
-            In other words, you can set, append, and prepend varflags just like
-            variables.
-            See the
-            "<link linkend='variable-flag-syntax'>Variable Flag Syntax</link>"
-            section for details.
-        </para>
-
-        <para>
-            BitBake has a defined set of varflags available for recipes and
-            classes.
-            Tasks support a number of these flags which control various
-            functionality of the task:
-            <itemizedlist>
-                <listitem><para><emphasis><filename>[cleandirs]</filename>:</emphasis>
-                    Empty directories that should be created before the
-                    task runs.
-                    Directories that already exist are removed and recreated
-                    to empty them.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[depends]</filename>:</emphasis>
-                    Controls inter-task dependencies.
-                    See the
-                    <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                    variable and the
-                    "<link linkend='inter-task-dependencies'>Inter-Task Dependencies</link>"
-                    section for more information.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[deptask]</filename>:</emphasis>
-                    Controls task build-time dependencies.
-                    See the
-                    <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                    variable and the
-                    "<link linkend='build-dependencies'>Build Dependencies</link>"
-                    section for more information.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[dirs]</filename>:</emphasis>
-                    Directories that should be created before the task runs.
-                    Directories that already exist are left as is.
-                    The last directory listed is used as the
-                    current working directory for the task.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[lockfiles]</filename>:</emphasis>
-                     Specifies one or more lockfiles to lock while the task
-                     executes.
-                     Only one task may hold a lockfile, and any task that
-                     attempts to lock an already locked file will block until
-                     the lock is released.
-                     You can use this variable flag to accomplish mutual
-                     exclusion.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[noexec]</filename>:</emphasis>
-                    When set to "1", marks the task as being empty, with
-                    no execution required.
-                    You can use the <filename>[noexec]</filename> flag to set up
-                    tasks as dependency placeholders, or to disable tasks defined
-                    elsewhere that are not needed in a particular recipe.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[nostamp]</filename>:</emphasis>
-                    When set to "1", tells BitBake to not generate a stamp
-                    file for a task, which implies the task should always
-                    be executed.
-                    <note><title>Caution</title>
-                        Any task that depends (possibly indirectly) on a
-                        <filename>[nostamp]</filename> task will always be
-                        executed as well.
-                        This can cause unnecessary rebuilding if you are
-                        not careful.
-                    </note>
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[number_threads]</filename>:</emphasis>
-                    Limits tasks to a specific number of simultaneous threads
-                    during execution.
-                    This varflag is useful when your build host has a large number
-                    of cores but certain tasks need to be rate-limited due to various
-                    kinds of resource constraints (e.g. to avoid network throttling).
-                    <filename>number_threads</filename> works similarly to the
-                    <link linkend='var-bb-BB_NUMBER_THREADS'><filename>BB_NUMBER_THREADS</filename></link>
-                    variable but is task-specific.</para>
-
-                    <para>Set the value globally.
-                    For example, the following makes sure the
-                    <filename>do_fetch</filename> task uses no more than two
-                    simultaneous execution threads:
-                    <literallayout class='monospaced'>
-     do_fetch[number_threads] = "2"
-                    </literallayout>
-                    <note><title>Warnings</title>
-                        <itemizedlist>
-                            <listitem><para>
-                                Setting the varflag in individual recipes rather
-                                than globally can result in unpredictable behavior.
-                                </para></listitem>
-                            <listitem><para>
-                                Setting the varflag to a value greater than the
-                                value used in the <filename>BB_NUMBER_THREADS</filename>
-                                variable causes <filename>number_threads</filename>
-                                to have no effect.
-                                </para></listitem>
-                        </itemizedlist>
-                    </note>
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[postfuncs]</filename>:</emphasis>
-                    List of functions to call after the completion of the task.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[prefuncs]</filename>:</emphasis>
-                    List of functions to call before the task executes.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[rdepends]</filename>:</emphasis>
-                    Controls inter-task runtime dependencies.
-                    See the
-                    <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>
-                    variable, the
-                    <link linkend='var-bb-RRECOMMENDS'><filename>RRECOMMENDS</filename></link>
-                    variable, and the
-                    "<link linkend='inter-task-dependencies'>Inter-Task Dependencies</link>"
-                    section for more information.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[rdeptask]</filename>:</emphasis>
-                    Controls task runtime dependencies.
-                    See the
-                    <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>
-                    variable, the
-                    <link linkend='var-bb-RRECOMMENDS'><filename>RRECOMMENDS</filename></link>
-                    variable, and the
-                    "<link linkend='runtime-dependencies'>Runtime Dependencies</link>"
-                    section for more information.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[recideptask]</filename>:</emphasis>
-                    When set in conjunction with
-                    <filename>recrdeptask</filename>, specifies a task that
-                    should be inspected for additional dependencies.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[recrdeptask]</filename>:</emphasis>
-                    Controls task recursive runtime dependencies.
-                    See the
-                    <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>
-                    variable, the
-                    <link linkend='var-bb-RRECOMMENDS'><filename>RRECOMMENDS</filename></link>
-                    variable, and the
-                    "<link linkend='recursive-dependencies'>Recursive Dependencies</link>"
-                    section for more information.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[stamp-extra-info]</filename>:</emphasis>
-                    Extra stamp information to append to the task's stamp.
-                    As an example, OpenEmbedded uses this flag to allow
-                    machine-specific tasks.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[umask]</filename>:</emphasis>
-                    The umask to run the task under.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            Several varflags are useful for controlling how signatures are
-            calculated for variables.
-            For more information on this process, see the
-            "<link linkend='checksums'>Checksums (Signatures)</link>"
-            section.
-            <itemizedlist>
-                <listitem><para><emphasis><filename>[vardeps]</filename>:</emphasis>
-                    Specifies a space-separated list of additional
-                    variables to add to a variable's dependencies
-                    for the purposes of calculating its signature.
-                    Adding variables to this list is useful, for example, when
-                    a function refers to a variable in a manner that
-                    does not allow BitBake to automatically determine
-                    that the variable is referred to.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[vardepsexclude]</filename>:</emphasis>
-                    Specifies a space-separated list of variables
-                    that should be excluded from a variable's dependencies
-                    for the purposes of calculating its signature.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[vardepvalue]</filename>:</emphasis>
-                    If set, instructs BitBake to ignore the actual
-                    value of the variable and instead use the specified
-                    value when calculating the variable's signature.
-                    </para></listitem>
-                <listitem><para><emphasis><filename>[vardepvalueexclude]</filename>:</emphasis>
-                    Specifies a pipe-separated list of strings to exclude
-                    from the variable's value when calculating the
-                    variable's signature.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id='events'>
-        <title>Events</title>
-
-        <para>
-            BitBake allows installation of event handlers within recipe
-            and class files.
-            Events are triggered at certain points during operation, such
-            as the beginning of operation against a given recipe
-            (i.e. <filename>*.bb</filename>), the start of a given task,
-            a task failure, a task success, and so forth.
-            The intent is to make it easy to do things like email
-            notification on build failures.
-        </para>
-
-        <para>
-            Following is an example event handler that prints the name
-            of the event and the content of the
-            <filename>FILE</filename> variable:
-            <literallayout class='monospaced'>
-     addhandler myclass_eventhandler
-     python myclass_eventhandler() {
-         from bb.event import getName
-         print("The name of the Event is %s" % getName(e))
-         print("The file we run for is %s" % d.getVar('FILE'))
-     }
-     myclass_eventhandler[eventmask] = "bb.event.BuildStarted bb.event.BuildCompleted"
-            </literallayout>
-            In the previous example, an eventmask has been set so that
-            the handler only sees the "BuildStarted" and "BuildCompleted"
-            events.
-            This event handler gets called every time an event matching
-            the eventmask is triggered.
-            A global variable "e" is defined, which represents the current
-            event.
-            With the <filename>getName(e)</filename> method, you can get
-            the name of the triggered event.
-            The global datastore is available as "d".
-            In legacy code, you might see "e.data" used to get the datastore.
-            However, realize that "e.data" is deprecated and you should use
-            "d" going forward.
-        </para>
-
-        <para>
-            The context of the datastore is appropriate to the event
-            in question.
-            For example, "BuildStarted" and "BuildCompleted" events run
-            before any tasks are executed so would be in the global
-            configuration datastore namespace.
-            No recipe-specific metadata exists in that namespace.
-            The "BuildStarted" and "BuildCompleted" events also run in
-            the main cooker/server process rather than any worker context.
-            Thus, any changes made to the datastore would be seen by other
-            cooker/server events within the current build but not seen
-            outside of that build or in any worker context.
-            Task events run in the actual tasks in question consequently
-            have recipe-specific and task-specific contents.
-            These events run in the worker context and are discarded at
-            the end of task execution.
-        </para>
-
-        <para>
-            During a standard build, the following common events might
-            occur.
-            The following events are the most common kinds of events that
-            most metadata might have an interest in viewing:
-            <itemizedlist>
-                <listitem><para>
-                    <filename>bb.event.ConfigParsed()</filename>:
-                    Fired when the base configuration; which consists of
-                    <filename>bitbake.conf</filename>,
-                    <filename>base.bbclass</filename> and any global
-                    <filename>INHERIT</filename> statements; has been parsed.
-                    You can see multiple such events when each of the
-                    workers parse the base configuration or if the server
-                    changes configuration and reparses.
-                    Any given datastore only has one such event executed
-                    against it, however.
-                    If
-                    <link linkende='var-bb-BB_INVALIDCONF'><filename>BB_INVALIDCONF</filename></link>
-                    is set in the datastore by the event handler, the
-                    configuration is reparsed and a new event triggered,
-                    allowing the metadata to update configuration.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.HeartbeatEvent()</filename>:
-                    Fires at regular time intervals of one second.
-                    You can configure the interval time using the
-                    <filename>BB_HEARTBEAT_EVENT</filename> variable.
-                    The event's "time" attribute is the
-                    <filename>time.time()</filename> value when the
-                    event is triggered.
-                    This event is useful for activities such as
-                    system state monitoring.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.ParseStarted()</filename>:
-                    Fired when BitBake is about to start parsing recipes.
-                    This event's "total" attribute represents the number of
-                    recipes BitBake plans to parse.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.ParseProgress()</filename>:
-                    Fired as parsing progresses.
-                    This event's "current" attribute is the number of
-                    recipes parsed as well as the "total" attribute.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.ParseCompleted()</filename>:
-                    Fired when parsing is complete.
-                    This event's "cached", "parsed", "skipped", "virtuals",
-                    "masked", and "errors" attributes provide statistics
-                    for the parsing results.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.BuildStarted()</filename>:
-                    Fired when a new build starts.
-                    BitBake fires multiple "BuildStarted" events (one per configuration)
-                    when multiple configuration (multiconfig) is enabled.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.build.TaskStarted()</filename>:
-                    Fired when a task starts.
-                    This event's "taskfile" attribute points to the recipe
-                    from which the task originates.
-                    The "taskname" attribute, which is the task's name,
-                    includes the <filename>do_</filename> prefix, and the
-                    "logfile" attribute point to where the task's output is
-                    stored.
-                    Finally, the "time" attribute is the task's execution start
-                    time.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.build.TaskInvalid()</filename>:
-                    Fired if BitBake tries to execute a task that does not exist.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.build.TaskFailedSilent()</filename>:
-                    Fired for setscene tasks that fail and should not be
-                    presented to the user verbosely.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.build.TaskFailed()</filename>:
-                    Fired for normal tasks that fail.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.build.TaskSucceeded()</filename>:
-                    Fired when a task successfully completes.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.BuildCompleted()</filename>:
-                    Fired when a build finishes.
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.cooker.CookerExit()</filename>:
-                    Fired when the BitBake server/cooker shuts down.
-                    This event is usually only seen by the UIs as a
-                    sign they should also shutdown.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-
-        <para>
-            This next list of example events occur based on specific
-            requests to the server.
-            These events are often used to communicate larger pieces of
-            information from the BitBake server to other parts of
-            BitBake such as user interfaces:
-            <itemizedlist>
-                <listitem><para>
-                    <filename>bb.event.TreeDataPreparationStarted()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.TreeDataPreparationProgress()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.TreeDataPreparationCompleted()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.DepTreeGenerated()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.CoreBaseFilesFound()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.ConfigFilePathFound()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.FilesMatchingFound()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.ConfigFilesFound()</filename>
-                    </para></listitem>
-                <listitem><para>
-                    <filename>bb.event.TargetsTreeGenerated()</filename>
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id='variants-class-extension-mechanism'>
-        <title>Variants - Class Extension Mechanism</title>
-
-        <para>
-            BitBake supports two features that facilitate creating
-            from a single recipe file multiple incarnations of that
-            recipe file where all incarnations are buildable.
-            These features are enabled through the
-            <link linkend='var-bb-BBCLASSEXTEND'><filename>BBCLASSEXTEND</filename></link>
-            and
-            <link linkend='var-bb-BBVERSIONS'><filename>BBVERSIONS</filename></link>
-            variables.
-            <note>
-                The mechanism for this class extension is extremely
-                specific to the implementation.
-                Usually, the recipe's
-                <link linkend='var-bb-PROVIDES'><filename>PROVIDES</filename></link>,
-                <link linkend='var-bb-PN'><filename>PN</filename></link>, and
-                <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                variables would need to be modified by the extension class.
-                For specific examples, see the OE-Core
-                <filename>native</filename>, <filename>nativesdk</filename>,
-                and <filename>multilib</filename> classes.
-            </note>
-            <itemizedlist>
-                <listitem><para><emphasis><filename>BBCLASSEXTEND</filename>:</emphasis>
-                    This variable is a space separated list of classes used to "extend" the
-                    recipe for each variant.
-                    Here is an example that results in a second incarnation of the current
-                    recipe being available.
-                    This second incarnation will have the "native" class inherited.
-                    <literallayout class='monospaced'>
-     BBCLASSEXTEND = "native"
-                    </literallayout></para></listitem>
-                <listitem><para><emphasis><filename>BBVERSIONS</filename>:</emphasis>
-                    This variable allows a single recipe to build multiple versions of a
-                    project from a single recipe file.
-                    You can also specify conditional metadata
-                    (using the
-                    <link linkend='var-bb-OVERRIDES'><filename>OVERRIDES</filename></link>
-                    mechanism) for a single version, or an optionally named range of versions.
-                    Here is an example:
-                    <literallayout class='monospaced'>
-     BBVERSIONS = "1.0 2.0 git"
-     SRC_URI_git = "git://someurl/somepath.git"
-
-     BBVERSIONS = "1.0.[0-6]:1.0.0+ \ 1.0.[7-9]:1.0.7+"
-     SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;patch=1"
-                    </literallayout>
-                    The name of the range defaults to the original version of the
-                    recipe.
-                    For example, in OpenEmbedded, the recipe file
-                    <filename>foo_1.0.0+.bb</filename> creates a default name range
-                    of <filename>1.0.0+</filename>.
-                    This is useful because the range name is not only placed
-                    into overrides, but it is also made available for the metadata to use
-                    in the variable that defines the base recipe versions for use in
-                    <filename>file://</filename> search paths
-                    (<link linkend='var-bb-FILESPATH'><filename>FILESPATH</filename></link>).
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id='dependencies'>
-        <title>Dependencies</title>
-
-        <para>
-            To allow for efficient parallel processing, BitBake handles
-            dependencies at the task level.
-            Dependencies can exist both between tasks within a single recipe
-            and between tasks in different recipes.
-            Following are examples of each:
-            <itemizedlist>
-                <listitem><para>For tasks within a single recipe, a
-                    recipe's <filename>do_configure</filename>
-                    task might need to complete before its
-                    <filename>do_compile</filename> task can run.
-                    </para></listitem>
-                <listitem><para>For tasks in different recipes, one
-                    recipe's <filename>do_configure</filename>
-                    task might require another recipe's
-                    <filename>do_populate_sysroot</filename>
-                    task to finish first such that the libraries and headers
-                    provided by the other recipe are available.
-                    </para></listitem>
-             </itemizedlist>
-         </para>
-
-         <para>
-             This section describes several ways to declare dependencies.
-             Remember, even though dependencies are declared in different ways, they
-             are all simply dependencies between tasks.
-         </para>
-
-        <section id='dependencies-internal-to-the-bb-file'>
-            <title>Dependencies Internal to the <filename>.bb</filename> File</title>
-
-            <para>
-                BitBake uses the <filename>addtask</filename> directive
-                to manage dependencies that are internal to a given recipe
-                file.
-                You can use the <filename>addtask</filename> directive to
-                indicate when a task is dependent on other tasks or when
-                other tasks depend on that recipe.
-                Here is an example:
-                <literallayout class='monospaced'>
-     addtask printdate after do_fetch before do_build
-                </literallayout>
-                In this example, the <filename>do_printdate</filename>
-                task depends on the completion of the
-                <filename>do_fetch</filename> task, and the
-                <filename>do_build</filename> task depends on the
-                completion of the <filename>do_printdate</filename>
-                task.
-                <note><para>
-                    For a task to run, it must be a direct or indirect
-                    dependency of some other task that is scheduled to
-                    run.</para>
-
-                    <para>For illustration, here are some examples:
-                    <itemizedlist>
-                        <listitem><para>
-                            The directive
-                            <filename>addtask mytask before do_configure</filename>
-                            causes <filename>do_mytask</filename> to run before
-                            <filename>do_configure</filename> runs.
-                            Be aware that <filename>do_mytask</filename> still only
-                            runs if its <link linkend='checksums'>input checksum</link>
-                            has changed since the last time it was run.
-                            Changes to the input checksum of
-                            <filename>do_mytask</filename> also indirectly cause
-                            <filename>do_configure</filename> to run.
-                            </para></listitem>
-                        <listitem><para>
-                            The directive
-                            <filename>addtask mytask after do_configure</filename>
-                            by itself never causes <filename>do_mytask</filename>
-                            to run.
-                            <filename>do_mytask</filename> can still be run manually
-                            as follows:
-                            <literallayout class='monospaced'>
-     $ bitbake <replaceable>recipe</replaceable> -c mytask
-                            </literallayout>
-                            Declaring <filename>do_mytask</filename> as a dependency
-                            of some other task that is scheduled to run also causes
-                            it to run.
-                            Regardless, the task runs after
-                            <filename>do_configure</filename>.
-                            </para></listitem>
-                    </itemizedlist></para>
-                </note>
-            </para>
-        </section>
-
-        <section id='build-dependencies'>
-            <title>Build Dependencies</title>
-
-            <para>
-                BitBake uses the
-                <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                variable to manage build time dependencies.
-                The <filename>[deptask]</filename> varflag for tasks
-                signifies the task of each
-                item listed in <filename>DEPENDS</filename> that must
-                complete before that task can be executed.
-                Here is an example:
-                <literallayout class='monospaced'>
-     do_configure[deptask] = "do_populate_sysroot"
-                </literallayout>
-                In this example, the <filename>do_populate_sysroot</filename>
-                task of each item in <filename>DEPENDS</filename> must complete before
-                <filename>do_configure</filename> can execute.
-            </para>
-        </section>
-
-        <section id='runtime-dependencies'>
-            <title>Runtime Dependencies</title>
-
-            <para>
-                BitBake uses the
-                <link linkend='var-bb-PACKAGES'><filename>PACKAGES</filename></link>,
-                <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>, and
-                <link linkend='var-bb-RRECOMMENDS'><filename>RRECOMMENDS</filename></link>
-                variables to manage runtime dependencies.
-            </para>
-
-            <para>
-                The <filename>PACKAGES</filename> variable lists runtime
-                packages.
-                Each of those packages can have <filename>RDEPENDS</filename> and
-                <filename>RRECOMMENDS</filename> runtime dependencies.
-                The <filename>[rdeptask]</filename> flag for tasks is used to
-                signify the task of each
-                item runtime dependency which must have completed before that
-                task can be executed.
-                <literallayout class='monospaced'>
-     do_package_qa[rdeptask] = "do_packagedata"
-                </literallayout>
-                In the previous example, the <filename>do_packagedata</filename>
-                task of each item in <filename>RDEPENDS</filename> must have
-                completed before <filename>do_package_qa</filename> can execute.
-                Although <filename>RDEPENDS</filename> contains entries from the
-                runtime dependency namespace, BitBake knows how to map them back
-                to the build-time dependency namespace, in which the tasks are defined.
-            </para>
-        </section>
-
-        <section id='recursive-dependencies'>
-            <title>Recursive Dependencies</title>
-
-            <para>
-                BitBake uses the <filename>[recrdeptask]</filename> flag to manage
-                recursive task dependencies.
-                BitBake looks through the build-time and runtime
-                dependencies of the current recipe, looks through
-                the task's inter-task
-                dependencies, and then adds dependencies for the
-                listed task.
-                Once BitBake has accomplished this, it recursively works through
-                the dependencies of those tasks.
-                Iterative passes continue until all dependencies are discovered
-                and added.
-            </para>
-
-            <para>
-                The <filename>[recrdeptask]</filename> flag is most commonly
-                used in high-level
-                recipes that need to wait for some task to finish "globally".
-                For example, <filename>image.bbclass</filename> has the following:
-                <literallayout class='monospaced'>
-     do_rootfs[recrdeptask] += "do_packagedata"
-                </literallayout>
-                This statement says that the <filename>do_packagedata</filename>
-                task of the current recipe and all recipes reachable
-                (by way of dependencies) from the
-                image recipe must run before the <filename>do_rootfs</filename>
-                task can run.
-            </para>
-
-            <para>
-                BitBake allows a task to recursively depend on itself by
-                referencing itself in the task list:
-                <literallayout class='monospaced'>
-     do_a[recrdeptask] = "do_a do_b"
-                </literallayout>
-                In the same way as before, this means that the <filename>do_a</filename>
-                and <filename>do_b</filename> tasks of the current recipe and all
-                recipes reachable (by way of dependencies) from the recipe
-                must run before the <filename>do_a</filename> task can run. In this
-                case BitBake will ignore the current recipe's <filename>do_a</filename>
-                task circular dependency on itself.
-            </para>
-        </section>
-
-        <section id='inter-task-dependencies'>
-            <title>Inter-Task Dependencies</title>
-
-            <para>
-                BitBake uses the <filename>[depends]</filename>
-                flag in a more generic form
-                to manage inter-task dependencies.
-                This more generic form allows for inter-dependency
-                checks for specific tasks rather than checks for
-                the data in <filename>DEPENDS</filename>.
-                Here is an example:
-                <literallayout class='monospaced'>
-     do_patch[depends] = "quilt-native:do_populate_sysroot"
-                </literallayout>
-                In this example, the <filename>do_populate_sysroot</filename>
-                task of the target <filename>quilt-native</filename>
-                must have completed before the
-                <filename>do_patch</filename> task can execute.
-            </para>
-
-            <para>
-                The <filename>[rdepends]</filename> flag works in a similar
-                way but takes targets
-                in the runtime namespace instead of the build-time dependency
-                namespace.
-            </para>
-        </section>
-    </section>
-
-    <section id='functions-you-can-call-from-within-python'>
-        <title>Functions You Can Call From Within Python</title>
-
-        <para>
-            BitBake provides many functions you can call from
-            within Python functions.
-            This section lists the most commonly used functions,
-            and mentions where to find others.
-        </para>
-
-        <section id='functions-for-accessing-datastore-variables'>
-            <title>Functions for Accessing Datastore Variables</title>
-
-            <para>
-                It is often necessary to access variables in the
-                BitBake datastore using Python functions.
-                The BitBake datastore has an API that allows you this
-                access.
-                Here is a list of available operations:
-            </para>
-
-            <para>
-                <informaltable frame='none'>
-                    <tgroup cols='2' align='left' colsep='1' rowsep='1'>
-                        <colspec colname='c1' colwidth='1*'/>
-                        <colspec colname='c2' colwidth='1*'/>
-                        <thead>
-                            <row>
-                                <entry align="left"><emphasis>Operation</emphasis></entry>
-                                <entry align="left"><emphasis>Description</emphasis></entry>
-                            </row>
-                        </thead>
-                        <tbody>
-                            <row>
-                                <entry align="left"><filename>d.getVar("X", expand)</filename></entry>
-                                <entry align="left">Returns the value of variable "X".
-                                    Using "expand=True" expands the value.
-                                    Returns "None" if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.setVar("X", "value")</filename></entry>
-                                <entry align="left">Sets the variable "X" to "value".</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.appendVar("X", "value")</filename></entry>
-                                <entry align="left">Adds "value" to the end of the variable "X".
-                                    Acts like <filename>d.setVar("X", "value")</filename>
-                                    if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.prependVar("X", "value")</filename></entry>
-                                <entry align="left">Adds "value" to the start of the variable "X".
-                                    Acts like <filename>d.setVar("X", "value")</filename>
-                                    if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.delVar("X")</filename></entry>
-                                <entry align="left">Deletes the variable "X" from the datastore.
-                                    Does nothing if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.renameVar("X", "Y")</filename></entry>
-                                <entry align="left">Renames the variable "X" to "Y".
-                                    Does nothing if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.getVarFlag("X", flag, expand)</filename></entry>
-                                <entry align="left">Returns the value of variable "X".
-                                    Using "expand=True" expands the value.
-                                    Returns "None" if either the variable "X" or the named flag
-                                    does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.setVarFlag("X", flag, "value")</filename></entry>
-                                <entry align="left">Sets the named flag for variable "X" to "value".</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.appendVarFlag("X", flag, "value")</filename></entry>
-                                <entry align="left">Appends "value" to the named flag on the
-                                    variable "X".
-                                    Acts like <filename>d.setVarFlag("X", flag, "value")</filename>
-                                    if the named flag does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.prependVarFlag("X", flag, "value")</filename></entry>
-                                <entry align="left">Prepends "value" to the named flag on
-                                    the variable "X".
-                                    Acts like <filename>d.setVarFlag("X", flag, "value")</filename>
-                                    if the named flag does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.delVarFlag("X", flag)</filename></entry>
-                                <entry align="left">Deletes the named flag on the variable
-                                    "X" from the datastore.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.setVarFlags("X", flagsdict)</filename></entry>
-                                <entry align="left">Sets the flags specified in
-                                    the <filename>flagsdict()</filename> parameter.
-                                    <filename>setVarFlags</filename> does not clear previous flags.
-                                    Think of this operation as <filename>addVarFlags</filename>.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.getVarFlags("X")</filename></entry>
-                                <entry align="left">Returns a <filename>flagsdict</filename>
-                                    of the flags for the variable "X".
-                                    Returns "None" if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.delVarFlags("X")</filename></entry>
-                                <entry align="left">Deletes all the flags for the variable "X".
-                                    Does nothing if the variable "X" does not exist.</entry>
-                            </row>
-                            <row>
-                                <entry align="left"><filename>d.expand(expression)</filename></entry>
-                                <entry align="left">Expands variable references in the specified
-                                    string expression.
-                                    References to variables that do not exist are left as is.
-                                    For example, <filename>d.expand("foo ${X}")</filename>
-                                    expands to the literal string "foo ${X}" if the
-                                    variable "X" does not exist.</entry>
-                            </row>
-                        </tbody>
-                    </tgroup>
-                </informaltable>
-            </para>
-        </section>
-
-        <section id='other-functions'>
-            <title>Other Functions</title>
-
-            <para>
-                You can find many other functions that can be called
-                from Python by looking at the source code of the
-                <filename>bb</filename> module, which is in
-                <filename>bitbake/lib/bb</filename>.
-                For example,
-                <filename>bitbake/lib/bb/utils.py</filename> includes
-                the commonly used functions
-                <filename>bb.utils.contains()</filename> and
-                <filename>bb.utils.mkdirhier()</filename>, which come
-                with docstrings.
-            </para>
-        </section>
-    </section>
-
-    <section id='task-checksums-and-setscene'>
-        <title>Task Checksums and Setscene</title>
-
-        <para>
-            BitBake uses checksums (or signatures) along with the setscene
-            to determine if a task needs to be run.
-            This section describes the process.
-            To help understand how BitBake does this, the section assumes an
-            OpenEmbedded metadata-based example.
-        </para>
-
-        <para>
-            These checksums are stored in
-            <link linkend='var-bb-STAMP'><filename>STAMP</filename></link>.
-            You can examine the checksums using the following BitBake command:
-            <literallayout class='monospaced'>
-     $ bitbake-dumpsigs
-            </literallayout>
-            This command returns the signature data in a readable format
-            that allows you to examine the inputs used when the
-            OpenEmbedded build system generates signatures.
-            For example, using <filename>bitbake-dumpsigs</filename>
-            allows you to examine the <filename>do_compile</filename>
-            task's “sigdata” for a C application (e.g.
-            <filename>bash</filename>).
-            Running the command also reveals that the “CC” variable is part of
-            the inputs that are hashed.
-            Any changes to this variable would invalidate the stamp and
-            cause the <filename>do_compile</filename> task to run.
-        </para>
-
-        <para>
-            The following list describes related variables:
-            <itemizedlist>
-                <listitem><para>
-                    <link linkend='var-bb-BB_HASHCHECK_FUNCTION'><filename>BB_HASHCHECK_FUNCTION</filename></link>:
-                    Specifies the name of the function to call during
-                    the "setscene" part of the task's execution in order
-                    to validate the list of task hashes.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_SETSCENE_DEPVALID'><filename>BB_SETSCENE_DEPVALID</filename></link>:
-                    Specifies a function BitBake calls that determines
-                    whether BitBake requires a setscene dependency to
-                    be met.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_SETSCENE_VERIFY_FUNCTION2'><filename>BB_SETSCENE_VERIFY_FUNCTION2</filename></link>:
-                    Specifies a function to call that verifies the list of
-                    planned task execution before the main task execution
-                    happens.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_STAMP_POLICY'><filename>BB_STAMP_POLICY</filename></link>:
-                    Defines the mode for comparing timestamps of stamp files.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_STAMP_WHITELIST'><filename>BB_STAMP_WHITELIST</filename></link>:
-                    Lists stamp files that are looked at when the stamp policy
-                    is "whitelist".
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-BB_TASKHASH'><filename>BB_TASKHASH</filename></link>:
-                    Within an executing task, this variable holds the hash
-                    of the task as returned by the currently enabled
-                    signature generator.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-STAMP'><filename>STAMP</filename></link>:
-                    The base path to create stamp files.
-                    </para></listitem>
-                <listitem><para>
-                    <link linkend='var-bb-STAMPCLEAN'><filename>STAMPCLEAN</filename></link>:
-                    Again, the base path to create stamp files but can use wildcards
-                    for matching a range of files for clean operations.
-                    </para></listitem>
-            </itemizedlist>
-        </para>
-    </section>
-
-    <section id='wildcard-support-in-variables'>
-        <title>Wildcard Support in Variables</title>
-
-        <para>
-            Support for wildcard use in variables varies depending on the
-            context in which it is used.
-            For example, some variables and file names allow limited use of
-            wildcards through the "<filename>%</filename>" and
-            "<filename>*</filename>" characters.
-            Other variables or names support Python's
-            <ulink url='https://docs.python.org/3/library/glob.html'><filename>glob</filename></ulink>
-            syntax,
-            <ulink url='https://docs.python.org/3/library/fnmatch.html#module-fnmatch'><filename>fnmatch</filename></ulink>
-            syntax, or
-            <ulink url='https://docs.python.org/3/library/re.html#re'><filename>Regular Expression (re)</filename></ulink>
-            syntax.
-        </para>
-
-        <para>
-            For variables that have wildcard suport, the
-            documentation describes which form of wildcard, its
-            use, and its limitations.
-        </para>
-    </section>
-
-</chapter>
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.rst b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.rst
new file mode 100644
index 00000000..489fa15f
--- /dev/null
+++ b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.rst
@@ -0,0 +1,1405 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+==================
+Variables Glossary
+==================
+
+|
+
+This chapter lists common variables used by BitBake and gives an
+overview of their function and contents.
+
+.. note::
+
+   Following are some points regarding the variables listed in this
+   glossary:
+
+   -  The variables listed in this glossary are specific to BitBake.
+      Consequently, the descriptions are limited to that context.
+
+   -  Also, variables exist in other systems that use BitBake (e.g. The
+      Yocto Project and OpenEmbedded) that have names identical to those
+      found in this glossary. For such cases, the variables in those
+      systems extend the functionality of the variable as it is
+      described here in this glossary.
+
+   -  Finally, there are variables mentioned in this glossary that do
+      not appear in the BitBake glossary. These other variables are
+      variables used in systems that use BitBake.
+
+.. glossary::
+
+   :term:`ASSUME_PROVIDED`
+      Lists recipe names (:term:`PN` values) BitBake does not
+      attempt to build. Instead, BitBake assumes these recipes have already
+      been built.
+
+      In OpenEmbedded-Core, ``ASSUME_PROVIDED`` mostly specifies native
+      tools that should not be built. An example is ``git-native``, which
+      when specified allows for the Git binary from the host to be used
+      rather than building ``git-native``.
+
+   :term:`AZ_SAS`
+      Azure Storage Shared Access Signature, when using the
+      :ref:`Azure Storage fetcher <bitbake-user-manual/bitbake-user-manual-fetching:fetchers>`
+      This variable can be defined to be used by the fetcher to authenticate
+      and gain access to non-public artifacts.
+      ::
+
+         AZ_SAS = ""se=2021-01-01&sp=r&sv=2018-11-09&sr=c&skoid=<skoid>&sig=<signature>""
+
+      For more information see Microsoft's Azure Storage documentation at
+      https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview
+
+
+   :term:`B`
+      The directory in which BitBake executes functions during a recipe's
+      build process.
+
+   :term:`BB_ALLOWED_NETWORKS`
+      Specifies a space-delimited list of hosts that the fetcher is allowed
+      to use to obtain the required source code. Following are
+      considerations surrounding this variable:
+
+      -  This host list is only used if
+         :term:`BB_NO_NETWORK` is either not set or
+         set to "0".
+
+      -  Limited support for the "``*``" wildcard character for matching
+         against the beginning of host names exists. For example, the
+         following setting matches ``git.gnu.org``, ``ftp.gnu.org``, and
+         ``foo.git.gnu.org``. ::
+
+            BB_ALLOWED_NETWORKS = "\*.gnu.org"
+
+         .. important::
+
+            The use of the "``*``" character only works at the beginning of
+            a host name and it must be isolated from the remainder of the
+            host name. You cannot use the wildcard character in any other
+            location of the name or combined with the front part of the
+            name.
+
+            For example, ``*.foo.bar`` is supported, while ``*aa.foo.bar``
+            is not.
+
+      -  Mirrors not in the host list are skipped and logged in debug.
+
+      -  Attempts to access networks not in the host list cause a failure.
+
+      Using ``BB_ALLOWED_NETWORKS`` in conjunction with
+      :term:`PREMIRRORS` is very useful. Adding the
+      host you want to use to ``PREMIRRORS`` results in the source code
+      being fetched from an allowed location and avoids raising an error
+      when a host that is not allowed is in a
+      :term:`SRC_URI` statement. This is because the
+      fetcher does not attempt to use the host listed in ``SRC_URI`` after
+      a successful fetch from the ``PREMIRRORS`` occurs.
+
+   :term:`BB_CONSOLELOG`
+      Specifies the path to a log file into which BitBake's user interface
+      writes output during the build.
+
+   :term:`BB_CURRENTTASK`
+      Contains the name of the currently running task. The name does not
+      include the ``do_`` prefix.
+
+   :term:`BB_DANGLINGAPPENDS_WARNONLY`
+      Defines how BitBake handles situations where an append file
+      (``.bbappend``) has no corresponding recipe file (``.bb``). This
+      condition often occurs when layers get out of sync (e.g. ``oe-core``
+      bumps a recipe version and the old recipe no longer exists and the
+      other layer has not been updated to the new version of the recipe
+      yet).
+
+      The default fatal behavior is safest because it is the sane reaction
+      given something is out of sync. It is important to realize when your
+      changes are no longer being applied.
+
+   :term:`BB_DEFAULT_TASK`
+      The default task to use when none is specified (e.g. with the ``-c``
+      command line option). The task name specified should not include the
+      ``do_`` prefix.
+
+   :term:`BB_DEFAULT_UMASK`
+      The default umask to apply to tasks if specified and no task specific
+      umask flag is set.
+
+   :term:`BB_DISKMON_DIRS`
+      Monitors disk space and available inodes during the build and allows
+      you to control the build based on these parameters.
+
+      Disk space monitoring is disabled by default. When setting this
+      variable, use the following form: ::
+
+         BB_DISKMON_DIRS = "<action>,<dir>,<threshold> [...]"
+
+         where:
+
+            <action> is:
+               ABORT:     Immediately abort the build when
+                          a threshold is broken.
+               STOPTASKS: Stop the build after the currently
+                          executing tasks have finished when
+                          a threshold is broken.
+               WARN:      Issue a warning but continue the
+                          build when a threshold is broken.
+                          Subsequent warnings are issued as
+                          defined by the
+                          BB_DISKMON_WARNINTERVAL variable,
+                          which must be defined.
+
+            <dir> is:
+               Any directory you choose. You can specify one or
+               more directories to monitor by separating the
+               groupings with a space.  If two directories are
+               on the same device, only the first directory
+               is monitored.
+
+            <threshold> is:
+               Either the minimum available disk space,
+               the minimum number of free inodes, or
+               both.  You must specify at least one.  To
+               omit one or the other, simply omit the value.
+               Specify the threshold using G, M, K for Gbytes,
+               Mbytes, and Kbytes, respectively. If you do
+               not specify G, M, or K, Kbytes is assumed by
+               default.  Do not use GB, MB, or KB.
+
+      Here are some examples: ::
+
+         BB_DISKMON_DIRS = "ABORT,${TMPDIR},1G,100K WARN,${SSTATE_DIR},1G,100K"
+         BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},1G"
+         BB_DISKMON_DIRS = "ABORT,${TMPDIR},,100K"
+
+      The first example works only if you also set the
+      :term:`BB_DISKMON_WARNINTERVAL`
+      variable. This example causes the build system to immediately abort
+      when either the disk space in ``${TMPDIR}`` drops below 1 Gbyte or
+      the available free inodes drops below 100 Kbytes. Because two
+      directories are provided with the variable, the build system also
+      issues a warning when the disk space in the ``${SSTATE_DIR}``
+      directory drops below 1 Gbyte or the number of free inodes drops
+      below 100 Kbytes. Subsequent warnings are issued during intervals as
+      defined by the ``BB_DISKMON_WARNINTERVAL`` variable.
+
+      The second example stops the build after all currently executing
+      tasks complete when the minimum disk space in the ``${TMPDIR}``
+      directory drops below 1 Gbyte. No disk monitoring occurs for the free
+      inodes in this case.
+
+      The final example immediately aborts the build when the number of
+      free inodes in the ``${TMPDIR}`` directory drops below 100 Kbytes. No
+      disk space monitoring for the directory itself occurs in this case.
+
+   :term:`BB_DISKMON_WARNINTERVAL`
+      Defines the disk space and free inode warning intervals.
+
+      If you are going to use the ``BB_DISKMON_WARNINTERVAL`` variable, you
+      must also use the :term:`BB_DISKMON_DIRS`
+      variable and define its action as "WARN". During the build,
+      subsequent warnings are issued each time disk space or number of free
+      inodes further reduces by the respective interval.
+
+      If you do not provide a ``BB_DISKMON_WARNINTERVAL`` variable and you
+      do use ``BB_DISKMON_DIRS`` with the "WARN" action, the disk
+      monitoring interval defaults to the following:
+      BB_DISKMON_WARNINTERVAL = "50M,5K"
+
+      When specifying the variable in your configuration file, use the
+      following form: ::
+
+         BB_DISKMON_WARNINTERVAL = "<disk_space_interval>,<disk_inode_interval>"
+
+         where:
+
+            <disk_space_interval> is:
+               An interval of memory expressed in either
+               G, M, or K for Gbytes, Mbytes, or Kbytes,
+               respectively. You cannot use GB, MB, or KB.
+
+            <disk_inode_interval> is:
+               An interval of free inodes expressed in either
+               G, M, or K for Gbytes, Mbytes, or Kbytes,
+               respectively. You cannot use GB, MB, or KB.
+
+      Here is an example: ::
+
+         BB_DISKMON_DIRS = "WARN,${SSTATE_DIR},1G,100K"
+         BB_DISKMON_WARNINTERVAL = "50M,5K"
+
+      These variables cause BitBake to
+      issue subsequent warnings each time the available disk space further
+      reduces by 50 Mbytes or the number of free inodes further reduces by
+      5 Kbytes in the ``${SSTATE_DIR}`` directory. Subsequent warnings
+      based on the interval occur each time a respective interval is
+      reached beyond the initial warning (i.e. 1 Gbytes and 100 Kbytes).
+
+   :term:`BB_ENV_WHITELIST`
+      Specifies the internal whitelist of variables to allow through from
+      the external environment into BitBake's datastore. If the value of
+      this variable is not specified (which is the default), the following
+      list is used: :term:`BBPATH`, :term:`BB_PRESERVE_ENV`,
+      :term:`BB_ENV_WHITELIST`, and :term:`BB_ENV_EXTRAWHITE`.
+
+      .. note::
+
+         You must set this variable in the external environment in order
+         for it to work.
+
+   :term:`BB_ENV_EXTRAWHITE`
+      Specifies an additional set of variables to allow through (whitelist)
+      from the external environment into BitBake's datastore. This list of
+      variables are on top of the internal list set in
+      :term:`BB_ENV_WHITELIST`.
+
+      .. note::
+
+         You must set this variable in the external environment in order
+         for it to work.
+
+   :term:`BB_FETCH_PREMIRRORONLY`
+      When set to "1", causes BitBake's fetcher module to only search
+      :term:`PREMIRRORS` for files. BitBake will not
+      search the main :term:`SRC_URI` or
+      :term:`MIRRORS`.
+
+   :term:`BB_FILENAME`
+      Contains the filename of the recipe that owns the currently running
+      task. For example, if the ``do_fetch`` task that resides in the
+      ``my-recipe.bb`` is executing, the ``BB_FILENAME`` variable contains
+      "/foo/path/my-recipe.bb".
+
+   :term:`BB_GENERATE_MIRROR_TARBALLS`
+      Causes tarballs of the Git repositories, including the Git metadata,
+      to be placed in the :term:`DL_DIR` directory. Anyone
+      wishing to create a source mirror would want to enable this variable.
+
+      For performance reasons, creating and placing tarballs of the Git
+      repositories is not the default action by BitBake. ::
+
+         BB_GENERATE_MIRROR_TARBALLS = "1"
+
+   :term:`BB_HASHCONFIG_WHITELIST`
+      Lists variables that are excluded from base configuration checksum,
+      which is used to determine if the cache can be reused.
+
+      One of the ways BitBake determines whether to re-parse the main
+      metadata is through checksums of the variables in the datastore of
+      the base configuration data. There are variables that you typically
+      want to exclude when checking whether or not to re-parse and thus
+      rebuild the cache. As an example, you would usually exclude ``TIME``
+      and ``DATE`` because these variables are always changing. If you did
+      not exclude them, BitBake would never reuse the cache.
+
+   :term:`BB_HASHBASE_WHITELIST`
+      Lists variables that are excluded from checksum and dependency data.
+      Variables that are excluded can therefore change without affecting
+      the checksum mechanism. A common example would be the variable for
+      the path of the build. BitBake's output should not (and usually does
+      not) depend on the directory in which it was built.
+
+   :term:`BB_HASHCHECK_FUNCTION`
+      Specifies the name of the function to call during the "setscene" part
+      of the task's execution in order to validate the list of task hashes.
+      The function returns the list of setscene tasks that should be
+      executed.
+
+      At this point in the execution of the code, the objective is to
+      quickly verify if a given setscene function is likely to work or not.
+      It's easier to check the list of setscene functions in one pass than
+      to call many individual tasks. The returned list need not be
+      completely accurate. A given setscene task can still later fail.
+      However, the more accurate the data returned, the more efficient the
+      build will be.
+
+   :term:`BB_INVALIDCONF`
+      Used in combination with the ``ConfigParsed`` event to trigger
+      re-parsing the base metadata (i.e. all the recipes). The
+      ``ConfigParsed`` event can set the variable to trigger the re-parse.
+      You must be careful to avoid recursive loops with this functionality.
+
+   :term:`BB_LOGCONFIG`
+      Specifies the name of a config file that contains the user logging
+      configuration. See
+      :ref:`bitbake-user-manual/bitbake-user-manual-execution:logging`
+      for additional information
+
+   :term:`BB_LOGFMT`
+      Specifies the name of the log files saved into
+      ``${``\ :term:`T`\ ``}``. By default, the ``BB_LOGFMT``
+      variable is undefined and the log file names get created using the
+      following form: ::
+
+         log.{task}.{pid}
+
+      If you want to force log files to take a specific name, you can set this
+      variable in a configuration file.
+
+   :term:`BB_NICE_LEVEL`
+      Allows BitBake to run at a specific priority (i.e. nice level).
+      System permissions usually mean that BitBake can reduce its priority
+      but not raise it again. See :term:`BB_TASK_NICE_LEVEL` for
+      additional information.
+
+   :term:`BB_NO_NETWORK`
+      Disables network access in the BitBake fetcher modules. With this
+      access disabled, any command that attempts to access the network
+      becomes an error.
+
+      Disabling network access is useful for testing source mirrors,
+      running builds when not connected to the Internet, and when operating
+      in certain kinds of firewall environments.
+
+   :term:`BB_NUMBER_THREADS`
+      The maximum number of tasks BitBake should run in parallel at any one
+      time. If your host development system supports multiple cores, a good
+      rule of thumb is to set this variable to twice the number of cores.
+
+   :term:`BB_NUMBER_PARSE_THREADS`
+      Sets the number of threads BitBake uses when parsing. By default, the
+      number of threads is equal to the number of cores on the system.
+
+   :term:`BB_ORIGENV`
+      Contains a copy of the original external environment in which BitBake
+      was run. The copy is taken before any whitelisted variable values are
+      filtered into BitBake's datastore.
+
+      .. note::
+
+         The contents of this variable is a datastore object that can be
+         queried using the normal datastore operations.
+
+   :term:`BB_PRESERVE_ENV`
+      Disables whitelisting and instead allows all variables through from
+      the external environment into BitBake's datastore.
+
+      .. note::
+
+         You must set this variable in the external environment in order
+         for it to work.
+
+   :term:`BB_RUNFMT`
+      Specifies the name of the executable script files (i.e. run files)
+      saved into ``${``\ :term:`T`\ ``}``. By default, the
+      ``BB_RUNFMT`` variable is undefined and the run file names get
+      created using the following form: ::
+
+         run.{task}.{pid}
+
+      If you want to force run files to take a specific name, you can set this
+      variable in a configuration file.
+
+   :term:`BB_RUNTASK`
+      Contains the name of the currently executing task. The value includes
+      the "do\_" prefix. For example, if the currently executing task is
+      ``do_config``, the value is "do_config".
+
+   :term:`BB_SCHEDULER`
+      Selects the name of the scheduler to use for the scheduling of
+      BitBake tasks. Three options exist:
+
+      -  *basic* - The basic framework from which everything derives. Using
+         this option causes tasks to be ordered numerically as they are
+         parsed.
+
+      -  *speed* - Executes tasks first that have more tasks depending on
+         them. The "speed" option is the default.
+
+      -  *completion* - Causes the scheduler to try to complete a given
+         recipe once its build has started.
+
+   :term:`BB_SCHEDULERS`
+      Defines custom schedulers to import. Custom schedulers need to be
+      derived from the ``RunQueueScheduler`` class.
+
+      For information how to select a scheduler, see the
+      :term:`BB_SCHEDULER` variable.
+
+   :term:`BB_SETSCENE_DEPVALID`
+      Specifies a function BitBake calls that determines whether BitBake
+      requires a setscene dependency to be met.
+
+      When running a setscene task, BitBake needs to know which
+      dependencies of that setscene task also need to be run. Whether
+      dependencies also need to be run is highly dependent on the metadata.
+      The function specified by this variable returns a "True" or "False"
+      depending on whether the dependency needs to be met.
+
+   :term:`BB_SETSCENE_VERIFY_FUNCTION2`
+      Specifies a function to call that verifies the list of planned task
+      execution before the main task execution happens. The function is
+      called once BitBake has a list of setscene tasks that have run and
+      either succeeded or failed.
+
+      The function allows for a task list check to see if they make sense.
+      Even if BitBake was planning to skip a task, the returned value of
+      the function can force BitBake to run the task, which is necessary
+      under certain metadata defined circumstances.
+
+   :term:`BB_SIGNATURE_EXCLUDE_FLAGS`
+      Lists variable flags (varflags) that can be safely excluded from
+      checksum and dependency data for keys in the datastore. When
+      generating checksum or dependency data for keys in the datastore, the
+      flags set against that key are normally included in the checksum.
+
+      For more information on varflags, see the
+      ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:variable flags`"
+      section.
+
+   :term:`BB_SIGNATURE_HANDLER`
+      Defines the name of the signature handler BitBake uses. The signature
+      handler defines the way stamp files are created and handled, if and
+      how the signature is incorporated into the stamps, and how the
+      signature itself is generated.
+
+      A new signature handler can be added by injecting a class derived
+      from the ``SignatureGenerator`` class into the global namespace.
+
+   :term:`BB_SRCREV_POLICY`
+      Defines the behavior of the fetcher when it interacts with source
+      control systems and dynamic source revisions. The
+      ``BB_SRCREV_POLICY`` variable is useful when working without a
+      network.
+
+      The variable can be set using one of two policies:
+
+      -  *cache* - Retains the value the system obtained previously rather
+         than querying the source control system each time.
+
+      -  *clear* - Queries the source controls system every time. With this
+         policy, there is no cache. The "clear" policy is the default.
+
+   :term:`BB_STAMP_POLICY`
+      Defines the mode used for how timestamps of stamp files are compared.
+      You can set the variable to one of the following modes:
+
+      -  *perfile* - Timestamp comparisons are only made between timestamps
+         of a specific recipe. This is the default mode.
+
+      -  *full* - Timestamp comparisons are made for all dependencies.
+
+      -  *whitelist* - Identical to "full" mode except timestamp
+         comparisons are made for recipes listed in the
+         :term:`BB_STAMP_WHITELIST` variable.
+
+      .. note::
+
+         Stamp policies are largely obsolete with the introduction of
+         setscene tasks.
+
+   :term:`BB_STAMP_WHITELIST`
+      Lists files whose stamp file timestamps are compared when the stamp
+      policy mode is set to "whitelist". For information on stamp policies,
+      see the :term:`BB_STAMP_POLICY` variable.
+
+   :term:`BB_STRICT_CHECKSUM`
+      Sets a more strict checksum mechanism for non-local URLs. Setting
+      this variable to a value causes BitBake to report an error if it
+      encounters a non-local URL that does not have at least one checksum
+      specified.
+
+   :term:`BB_TASK_IONICE_LEVEL`
+      Allows adjustment of a task's Input/Output priority. During
+      Autobuilder testing, random failures can occur for tasks due to I/O
+      starvation. These failures occur during various QEMU runtime
+      timeouts. You can use the ``BB_TASK_IONICE_LEVEL`` variable to adjust
+      the I/O priority of these tasks.
+
+      .. note::
+
+         This variable works similarly to the :term:`BB_TASK_NICE_LEVEL`
+         variable except with a task's I/O priorities.
+
+      Set the variable as follows: ::
+
+         BB_TASK_IONICE_LEVEL = "class.prio"
+
+      For *class*, the default value is "2", which is a best effort. You can use
+      "1" for realtime and "3" for idle. If you want to use realtime, you
+      must have superuser privileges.
+
+      For *prio*, you can use any value from "0", which is the highest
+      priority, to "7", which is the lowest. The default value is "4". You
+      do not need any special privileges to use this range of priority
+      values.
+
+      .. note::
+
+         In order for your I/O priority settings to take effect, you need the
+         Completely Fair Queuing (CFQ) Scheduler selected for the backing block
+         device. To select the scheduler, use the following command form where
+         device is the device (e.g. sda, sdb, and so forth): ::
+
+            $ sudo sh -c "echo cfq > /sys/block/device/queu/scheduler"
+
+   :term:`BB_TASK_NICE_LEVEL`
+      Allows specific tasks to change their priority (i.e. nice level).
+
+      You can use this variable in combination with task overrides to raise
+      or lower priorities of specific tasks. For example, on the `Yocto
+      Project <http://www.yoctoproject.org>`__ autobuilder, QEMU emulation
+      in images is given a higher priority as compared to build tasks to
+      ensure that images do not suffer timeouts on loaded systems.
+
+   :term:`BB_TASKHASH`
+      Within an executing task, this variable holds the hash of the task as
+      returned by the currently enabled signature generator.
+
+   :term:`BB_VERBOSE_LOGS`
+      Controls how verbose BitBake is during builds. If set, shell scripts
+      echo commands and shell script output appears on standard out
+      (stdout).
+
+   :term:`BB_WORKERCONTEXT`
+      Specifies if the current context is executing a task. BitBake sets
+      this variable to "1" when a task is being executed. The value is not
+      set when the task is in server context during parsing or event
+      handling.
+
+   :term:`BBCLASSEXTEND`
+      Allows you to extend a recipe so that it builds variants of the
+      software. Some examples of these variants for recipes from the
+      OpenEmbedded-Core metadata are "natives" such as ``quilt-native``,
+      which is a copy of Quilt built to run on the build system; "crosses"
+      such as ``gcc-cross``, which is a compiler built to run on the build
+      machine but produces binaries that run on the target ``MACHINE``;
+      "nativesdk", which targets the SDK machine instead of ``MACHINE``;
+      and "mulitlibs" in the form "``multilib:``\ multilib_name".
+
+      To build a different variant of the recipe with a minimal amount of
+      code, it usually is as simple as adding the variable to your recipe.
+      Here are two examples. The "native" variants are from the
+      OpenEmbedded-Core metadata: ::
+
+         BBCLASSEXTEND =+ "native nativesdk"
+         BBCLASSEXTEND =+ "multilib:multilib_name"
+
+      .. note::
+
+         Internally, the ``BBCLASSEXTEND`` mechanism generates recipe
+         variants by rewriting variable values and applying overrides such
+         as ``_class-native``. For example, to generate a native version of
+         a recipe, a :term:`DEPENDS` on "foo" is
+         rewritten to a ``DEPENDS`` on "foo-native".
+
+         Even when using ``BBCLASSEXTEND``, the recipe is only parsed once.
+         Parsing once adds some limitations. For example, it is not
+         possible to include a different file depending on the variant,
+         since ``include`` statements are processed when the recipe is
+         parsed.
+
+   :term:`BBDEBUG`
+      Sets the BitBake debug output level to a specific value as
+      incremented by the ``-D`` command line option.
+
+      .. note::
+
+         You must set this variable in the external environment in order
+         for it to work.
+
+   :term:`BBFILE_COLLECTIONS`
+      Lists the names of configured layers. These names are used to find
+      the other ``BBFILE_*`` variables. Typically, each layer appends its
+      name to this variable in its ``conf/layer.conf`` file.
+
+   :term:`BBFILE_PATTERN`
+      Variable that expands to match files from
+      :term:`BBFILES` in a particular layer. This
+      variable is used in the ``conf/layer.conf`` file and must be suffixed
+      with the name of the specific layer (e.g.
+      ``BBFILE_PATTERN_emenlow``).
+
+   :term:`BBFILE_PRIORITY`
+      Assigns the priority for recipe files in each layer.
+
+      This variable is useful in situations where the same recipe appears
+      in more than one layer. Setting this variable allows you to
+      prioritize a layer against other layers that contain the same recipe
+      - effectively letting you control the precedence for the multiple
+      layers. The precedence established through this variable stands
+      regardless of a recipe's version (:term:`PV` variable).
+      For example, a layer that has a recipe with a higher ``PV`` value but
+      for which the ``BBFILE_PRIORITY`` is set to have a lower precedence
+      still has a lower precedence.
+
+      A larger value for the ``BBFILE_PRIORITY`` variable results in a
+      higher precedence. For example, the value 6 has a higher precedence
+      than the value 5. If not specified, the ``BBFILE_PRIORITY`` variable
+      is set based on layer dependencies (see the ``LAYERDEPENDS`` variable
+      for more information. The default priority, if unspecified for a
+      layer with no dependencies, is the lowest defined priority + 1 (or 1
+      if no priorities are defined).
+
+      .. tip::
+
+         You can use the command bitbake-layers show-layers to list all
+         configured layers along with their priorities.
+
+   :term:`BBFILES`
+      A space-separated list of recipe files BitBake uses to build
+      software.
+
+      When specifying recipe files, you can pattern match using Python's
+      `glob <https://docs.python.org/3/library/glob.html>`_ syntax.
+      For details on the syntax, see the documentation by following the
+      previous link.
+
+   :term:`BBFILES_DYNAMIC`
+      Activates content depending on presence of identified layers.  You
+      identify the layers by the collections that the layers define.
+
+      Use the ``BBFILES_DYNAMIC`` variable to avoid ``.bbappend`` files whose
+      corresponding ``.bb`` file is in a layer that attempts to modify other
+      layers through ``.bbappend`` but does not want to introduce a hard
+      dependency on those other layers.
+
+      Additionally you can prefix the rule with "!" to add ``.bbappend`` and
+      ``.bb`` files in case a layer is not present.  Use this avoid hard
+      dependency on those other layers.
+
+      Use the following form for ``BBFILES_DYNAMIC``: ::
+
+         collection_name:filename_pattern
+
+      The following example identifies two collection names and two filename
+      patterns: ::
+
+         BBFILES_DYNAMIC += "\
+             clang-layer:${LAYERDIR}/bbappends/meta-clang/*/*/*.bbappend \
+             core:${LAYERDIR}/bbappends/openembedded-core/meta/*/*/*.bbappend \
+         "
+
+      When the collection name is prefixed with "!" it will add the file pattern in case
+      the layer is absent: ::
+
+         BBFILES_DYNAMIC += "\
+             !clang-layer:${LAYERDIR}/backfill/meta-clang/*/*/*.bb \
+         "
+
+      This next example shows an error message that occurs because invalid
+      entries are found, which cause parsing to abort: ::
+
+         ERROR: BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:
+         /work/my-layer/bbappends/meta-security-isafw/*/*/*.bbappend
+         /work/my-layer/bbappends/openembedded-core/meta/*/*/*.bbappend
+
+   :term:`BBINCLUDED`
+      Contains a space-separated list of all of all files that BitBake's
+      parser included during parsing of the current file.
+
+   :term:`BBINCLUDELOGS`
+      If set to a value, enables printing the task log when reporting a
+      failed task.
+
+   :term:`BBINCLUDELOGS_LINES`
+      If :term:`BBINCLUDELOGS` is set, specifies
+      the maximum number of lines from the task log file to print when
+      reporting a failed task. If you do not set ``BBINCLUDELOGS_LINES``,
+      the entire log is printed.
+
+   :term:`BBLAYERS`
+      Lists the layers to enable during the build. This variable is defined
+      in the ``bblayers.conf`` configuration file in the build directory.
+      Here is an example: ::
+
+         BBLAYERS = " \
+             /home/scottrif/poky/meta \
+             /home/scottrif/poky/meta-yocto \
+             /home/scottrif/poky/meta-yocto-bsp \
+             /home/scottrif/poky/meta-mykernel \
+         "
+
+      This example enables four layers, one of which is a custom, user-defined
+      layer named ``meta-mykernel``.
+
+   :term:`BBLAYERS_FETCH_DIR`
+      Sets the base location where layers are stored. This setting is used
+      in conjunction with ``bitbake-layers layerindex-fetch`` and tells
+      ``bitbake-layers`` where to place the fetched layers.
+
+   :term:`BBMASK`
+      Prevents BitBake from processing recipes and recipe append files.
+
+      You can use the ``BBMASK`` variable to "hide" these ``.bb`` and
+      ``.bbappend`` files. BitBake ignores any recipe or recipe append
+      files that match any of the expressions. It is as if BitBake does not
+      see them at all. Consequently, matching files are not parsed or
+      otherwise used by BitBake.
+
+      The values you provide are passed to Python's regular expression
+      compiler. Consequently, the syntax follows Python's Regular
+      Expression (re) syntax. The expressions are compared against the full
+      paths to the files. For complete syntax information, see Python's
+      documentation at http://docs.python.org/3/library/re.html.
+
+      The following example uses a complete regular expression to tell
+      BitBake to ignore all recipe and recipe append files in the
+      ``meta-ti/recipes-misc/`` directory: ::
+
+         BBMASK = "meta-ti/recipes-misc/"
+
+      If you want to mask out multiple directories or recipes, you can
+      specify multiple regular expression fragments. This next example
+      masks out multiple directories and individual recipes: ::
+
+         BBMASK += "/meta-ti/recipes-misc/ meta-ti/recipes-ti/packagegroup/"
+         BBMASK += "/meta-oe/recipes-support/"
+         BBMASK += "/meta-foo/.*/openldap"
+         BBMASK += "opencv.*\.bbappend"
+         BBMASK += "lzma"
+
+      .. note::
+
+         When specifying a directory name, use the trailing slash character
+         to ensure you match just that directory name.
+
+   :term:`BBMULTICONFIG`
+      Enables BitBake to perform multiple configuration builds and lists
+      each separate configuration (multiconfig). You can use this variable
+      to cause BitBake to build multiple targets where each target has a
+      separate configuration. Define ``BBMULTICONFIG`` in your
+      ``conf/local.conf`` configuration file.
+
+      As an example, the following line specifies three multiconfigs, each
+      having a separate configuration file: ::
+
+         BBMULTIFONFIG = "configA configB configC"
+
+      Each configuration file you use must reside in the
+      build directory within a directory named ``conf/multiconfig`` (e.g.
+      build_directory\ ``/conf/multiconfig/configA.conf``).
+
+      For information on how to use ``BBMULTICONFIG`` in an environment
+      that supports building targets with multiple configurations, see the
+      ":ref:`bitbake-user-manual/bitbake-user-manual-intro:executing a multiple configuration build`"
+      section.
+
+   :term:`BBPATH`
+      Used by BitBake to locate class (``.bbclass``) and configuration
+      (``.conf``) files. This variable is analogous to the ``PATH``
+      variable.
+
+      If you run BitBake from a directory outside of the build directory,
+      you must be sure to set ``BBPATH`` to point to the build directory.
+      Set the variable as you would any environment variable and then run
+      BitBake: ::
+
+         $ BBPATH="build_directory"
+         $ export BBPATH
+         $ bitbake target
+
+   :term:`BBSERVER`
+      Points to the server that runs memory-resident BitBake. The variable
+      is only used when you employ memory-resident BitBake.
+
+   :term:`BBTARGETS`
+      Allows you to use a configuration file to add to the list of
+      command-line target recipes you want to build.
+
+   :term:`BBVERSIONS`
+      Allows a single recipe to build multiple versions of a project from a
+      single recipe file. You also able to specify conditional metadata
+      using the :term:`OVERRIDES` mechanism for a
+      single version or for an optionally named range of versions.
+
+      For more information on ``BBVERSIONS``, see the
+      ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:variants - class extension mechanism`"
+      section.
+
+   :term:`BITBAKE_UI`
+      Used to specify the UI module to use when running BitBake. Using this
+      variable is equivalent to using the ``-u`` command-line option.
+
+      .. note::
+
+         You must set this variable in the external environment in order
+         for it to work.
+
+   :term:`BUILDNAME`
+      A name assigned to the build. The name defaults to a datetime stamp
+      of when the build was started but can be defined by the metadata.
+
+   :term:`BZRDIR`
+      The directory in which files checked out of a Bazaar system are
+      stored.
+
+   :term:`CACHE`
+      Specifies the directory BitBake uses to store a cache of the metadata
+      so it does not need to be parsed every time BitBake is started.
+
+   :term:`CVSDIR`
+      The directory in which files checked out under the CVS system are
+      stored.
+
+   :term:`DEFAULT_PREFERENCE`
+      Specifies a weak bias for recipe selection priority.
+
+      The most common usage of this is variable is to set it to "-1" within
+      a recipe for a development version of a piece of software. Using the
+      variable in this way causes the stable version of the recipe to build
+      by default in the absence of ``PREFERRED_VERSION`` being used to
+      build the development version.
+
+      .. note::
+
+         The bias provided by DEFAULT_PREFERENCE is weak and is overridden by
+         :term:`BBFILE_PRIORITY` if that variable is different between two
+         layers that contain different versions of the same recipe.
+
+   :term:`DEPENDS`
+      Lists a recipe's build-time dependencies (i.e. other recipe files).
+
+      Consider this simple example for two recipes named "a" and "b" that
+      produce similarly named packages. In this example, the ``DEPENDS``
+      statement appears in the "a" recipe: ::
+
+         DEPENDS = "b"
+
+      Here, the dependency is such that the ``do_configure`` task for recipe "a"
+      depends on the ``do_populate_sysroot`` task of recipe "b". This means
+      anything that recipe "b" puts into sysroot is available when recipe "a" is
+      configuring itself.
+
+      For information on runtime dependencies, see the :term:`RDEPENDS`
+      variable.
+
+   :term:`DESCRIPTION`
+      A long description for the recipe.
+
+   :term:`DL_DIR`
+      The central download directory used by the build process to store
+      downloads. By default, ``DL_DIR`` gets files suitable for mirroring for
+      everything except Git repositories. If you want tarballs of Git
+      repositories, use the :term:`BB_GENERATE_MIRROR_TARBALLS` variable.
+
+   :term:`EXCLUDE_FROM_WORLD`
+      Directs BitBake to exclude a recipe from world builds (i.e.
+      ``bitbake world``). During world builds, BitBake locates, parses and
+      builds all recipes found in every layer exposed in the
+      ``bblayers.conf`` configuration file.
+
+      To exclude a recipe from a world build using this variable, set the
+      variable to "1" in the recipe.
+
+      .. note::
+
+         Recipes added to ``EXCLUDE_FROM_WORLD`` may still be built during a world
+         build in order to satisfy dependencies of other recipes. Adding a
+         recipe to ``EXCLUDE_FROM_WORLD`` only ensures that the recipe is not
+         explicitly added to the list of build targets in a world build.
+
+   :term:`FAKEROOT`
+      Contains the command to use when running a shell script in a fakeroot
+      environment. The ``FAKEROOT`` variable is obsolete and has been
+      replaced by the other ``FAKEROOT*`` variables. See these entries in
+      the glossary for more information.
+
+   :term:`FAKEROOTBASEENV`
+      Lists environment variables to set when executing the command defined
+      by :term:`FAKEROOTCMD` that starts the
+      bitbake-worker process in the fakeroot environment.
+
+   :term:`FAKEROOTCMD`
+      Contains the command that starts the bitbake-worker process in the
+      fakeroot environment.
+
+   :term:`FAKEROOTDIRS`
+      Lists directories to create before running a task in the fakeroot
+      environment.
+
+   :term:`FAKEROOTENV`
+      Lists environment variables to set when running a task in the
+      fakeroot environment. For additional information on environment
+      variables and the fakeroot environment, see the
+      :term:`FAKEROOTBASEENV` variable.
+
+   :term:`FAKEROOTNOENV`
+      Lists environment variables to set when running a task that is not in
+      the fakeroot environment. For additional information on environment
+      variables and the fakeroot environment, see the
+      :term:`FAKEROOTENV` variable.
+
+   :term:`FETCHCMD`
+      Defines the command the BitBake fetcher module executes when running
+      fetch operations. You need to use an override suffix when you use the
+      variable (e.g. ``FETCHCMD_git`` or ``FETCHCMD_svn``).
+
+   :term:`FILE`
+      Points at the current file. BitBake sets this variable during the
+      parsing process to identify the file being parsed. BitBake also sets
+      this variable when a recipe is being executed to identify the recipe
+      file.
+
+   :term:`FILESPATH`
+      Specifies directories BitBake uses when searching for patches and
+      files. The "local" fetcher module uses these directories when
+      handling ``file://`` URLs. The variable behaves like a shell ``PATH``
+      environment variable. The value is a colon-separated list of
+      directories that are searched left-to-right in order.
+
+   :term:`GITDIR`
+      The directory in which a local copy of a Git repository is stored
+      when it is cloned.
+
+   :term:`HGDIR`
+      The directory in which files checked out of a Mercurial system are
+      stored.
+
+   :term:`HOMEPAGE`
+      Website where more information about the software the recipe is
+      building can be found.
+
+   :term:`INHERIT`
+      Causes the named class or classes to be inherited globally. Anonymous
+      functions in the class or classes are not executed for the base
+      configuration and in each individual recipe. The OpenEmbedded build
+      system ignores changes to ``INHERIT`` in individual recipes.
+
+      For more information on ``INHERIT``, see the
+      ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:\`\`inherit\`\` configuration directive`"
+      section.
+
+   :term:`LAYERDEPENDS`
+      Lists the layers, separated by spaces, upon which this recipe
+      depends. Optionally, you can specify a specific layer version for a
+      dependency by adding it to the end of the layer name with a colon,
+      (e.g. "anotherlayer:3" to be compared against
+      :term:`LAYERVERSION`\ ``_anotherlayer`` in
+      this case). BitBake produces an error if any dependency is missing or
+      the version numbers do not match exactly (if specified).
+
+      You use this variable in the ``conf/layer.conf`` file. You must also
+      use the specific layer name as a suffix to the variable (e.g.
+      ``LAYERDEPENDS_mylayer``).
+
+   :term:`LAYERDIR`
+      When used inside the ``layer.conf`` configuration file, this variable
+      provides the path of the current layer. This variable is not
+      available outside of ``layer.conf`` and references are expanded
+      immediately when parsing of the file completes.
+
+   :term:`LAYERDIR_RE`
+      When used inside the ``layer.conf`` configuration file, this variable
+      provides the path of the current layer, escaped for use in a regular
+      expression (:term:`BBFILE_PATTERN`). This
+      variable is not available outside of ``layer.conf`` and references
+      are expanded immediately when parsing of the file completes.
+
+   :term:`LAYERVERSION`
+      Optionally specifies the version of a layer as a single number. You
+      can use this variable within
+      :term:`LAYERDEPENDS` for another layer in
+      order to depend on a specific version of the layer.
+
+      You use this variable in the ``conf/layer.conf`` file. You must also
+      use the specific layer name as a suffix to the variable (e.g.
+      ``LAYERDEPENDS_mylayer``).
+
+   :term:`LICENSE`
+      The list of source licenses for the recipe.
+
+   :term:`MIRRORS`
+      Specifies additional paths from which BitBake gets source code. When
+      the build system searches for source code, it first tries the local
+      download directory. If that location fails, the build system tries
+      locations defined by :term:`PREMIRRORS`, the
+      upstream source, and then locations specified by ``MIRRORS`` in that
+      order.
+
+   :term:`MULTI_PROVIDER_WHITELIST`
+      Allows you to suppress BitBake warnings caused when building two
+      separate recipes that provide the same output.
+
+      BitBake normally issues a warning when building two different recipes
+      where each provides the same output. This scenario is usually
+      something the user does not want. However, cases do exist where it
+      makes sense, particularly in the ``virtual/*`` namespace. You can use
+      this variable to suppress BitBake's warnings.
+
+      To use the variable, list provider names (e.g. recipe names,
+      ``virtual/kernel``, and so forth).
+
+   :term:`OVERRIDES`
+      BitBake uses ``OVERRIDES`` to control what variables are overridden
+      after BitBake parses recipes and configuration files.
+
+      Following is a simple example that uses an overrides list based on
+      machine architectures: OVERRIDES = "arm:x86:mips:powerpc" You can
+      find information on how to use ``OVERRIDES`` in the
+      ":ref:`bitbake-user-manual/bitbake-user-manual-metadata:conditional syntax
+      (overrides)`" section.
+
+   :term:`P4DIR`
+      The directory in which a local copy of a Perforce depot is stored
+      when it is fetched.
+
+   :term:`PACKAGES`
+      The list of packages the recipe creates.
+
+   :term:`PACKAGES_DYNAMIC`
+      A promise that your recipe satisfies runtime dependencies for
+      optional modules that are found in other recipes.
+      ``PACKAGES_DYNAMIC`` does not actually satisfy the dependencies, it
+      only states that they should be satisfied. For example, if a hard,
+      runtime dependency (:term:`RDEPENDS`) of another
+      package is satisfied during the build through the
+      ``PACKAGES_DYNAMIC`` variable, but a package with the module name is
+      never actually produced, then the other package will be broken.
+
+   :term:`PE`
+      The epoch of the recipe. By default, this variable is unset. The
+      variable is used to make upgrades possible when the versioning scheme
+      changes in some backwards incompatible way.
+
+   :term:`PERSISTENT_DIR`
+      Specifies the directory BitBake uses to store data that should be
+      preserved between builds. In particular, the data stored is the data
+      that uses BitBake's persistent data API and the data used by the PR
+      Server and PR Service.
+
+   :term:`PF`
+      Specifies the recipe or package name and includes all version and
+      revision numbers (i.e. ``eglibc-2.13-r20+svnr15508/`` and
+      ``bash-4.2-r1/``).
+
+   :term:`PN`
+      The recipe name.
+
+   :term:`PR`
+      The revision of the recipe.
+
+   :term:`PREFERRED_PROVIDER`
+      Determines which recipe should be given preference when multiple
+      recipes provide the same item. You should always suffix the variable
+      with the name of the provided item, and you should set it to the
+      :term:`PN` of the recipe to which you want to give
+      precedence. Some examples: ::
+
+         PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
+         PREFERRED_PROVIDER_virtual/xserver = "xserver-xf86"
+         PREFERRED_PROVIDER_virtual/libgl ?= "mesa"
+
+   :term:`PREFERRED_PROVIDERS`
+      Determines which recipe should be given preference for cases where
+      multiple recipes provide the same item. Functionally,
+      ``PREFERRED_PROVIDERS`` is identical to
+      :term:`PREFERRED_PROVIDER`. However, the ``PREFERRED_PROVIDERS`` variable
+      lets you define preferences for multiple situations using the following
+      form: ::
+
+         PREFERRED_PROVIDERS = "xxx:yyy aaa:bbb ..."
+
+      This form is a convenient replacement for the following: ::
+
+         PREFERRED_PROVIDER_xxx = "yyy"
+         PREFERRED_PROVIDER_aaa = "bbb"
+
+   :term:`PREFERRED_VERSION`
+      If there are multiple versions of a recipe available, this variable
+      determines which version should be given preference. You must always
+      suffix the variable with the :term:`PN` you want to
+      select, and you should set :term:`PV` accordingly for
+      precedence.
+
+      The ``PREFERRED_VERSION`` variable supports limited wildcard use
+      through the "``%``" character. You can use the character to match any
+      number of characters, which can be useful when specifying versions
+      that contain long revision numbers that potentially change. Here are
+      two examples: ::
+
+         PREFERRED_VERSION_python = "2.7.3"
+         PREFERRED_VERSION_linux-yocto = "4.12%"
+
+      .. important::
+
+         The use of the " % " character is limited in that it only works at the
+         end of the string. You cannot use the wildcard character in any other
+         location of the string.
+
+      If a recipe with the specified version is not available, a warning
+      message will be shown. See :term:`REQUIRED_VERSION` if you want this
+      to be an error instead.
+
+   :term:`PREMIRRORS`
+      Specifies additional paths from which BitBake gets source code. When
+      the build system searches for source code, it first tries the local
+      download directory. If that location fails, the build system tries
+      locations defined by ``PREMIRRORS``, the upstream source, and then
+      locations specified by :term:`MIRRORS` in that order.
+
+      Typically, you would add a specific server for the build system to
+      attempt before any others by adding something like the following to
+      your configuration: ::
+
+         PREMIRRORS_prepend = "\
+         git://.*/.* http://www.yoctoproject.org/sources/ \n \
+         ftp://.*/.* http://www.yoctoproject.org/sources/ \n \
+         http://.*/.* http://www.yoctoproject.org/sources/ \n \
+         https://.*/.* http://www.yoctoproject.org/sources/ \n"
+
+      These changes cause the build system to intercept Git, FTP, HTTP, and
+      HTTPS requests and direct them to the ``http://`` sources mirror. You can
+      use ``file://`` URLs to point to local directories or network shares as
+      well.
+
+   :term:`PROVIDES`
+      A list of aliases by which a particular recipe can be known. By
+      default, a recipe's own ``PN`` is implicitly already in its
+      ``PROVIDES`` list. If a recipe uses ``PROVIDES``, the additional
+      aliases are synonyms for the recipe and can be useful satisfying
+      dependencies of other recipes during the build as specified by
+      ``DEPENDS``.
+
+      Consider the following example ``PROVIDES`` statement from a recipe
+      file ``libav_0.8.11.bb``: ::
+
+         PROVIDES += "libpostproc"
+
+      The ``PROVIDES`` statement results in the "libav" recipe also being known
+      as "libpostproc".
+
+      In addition to providing recipes under alternate names, the
+      ``PROVIDES`` mechanism is also used to implement virtual targets. A
+      virtual target is a name that corresponds to some particular
+      functionality (e.g. a Linux kernel). Recipes that provide the
+      functionality in question list the virtual target in ``PROVIDES``.
+      Recipes that depend on the functionality in question can include the
+      virtual target in :term:`DEPENDS` to leave the
+      choice of provider open.
+
+      Conventionally, virtual targets have names on the form
+      "virtual/function" (e.g. "virtual/kernel"). The slash is simply part
+      of the name and has no syntactical significance.
+
+   :term:`PRSERV_HOST`
+      The network based :term:`PR` service host and port.
+
+      Following is an example of how the ``PRSERV_HOST`` variable is set: ::
+
+         PRSERV_HOST = "localhost:0"
+
+      You must set the variable if you want to automatically start a local PR
+      service. You can set ``PRSERV_HOST`` to other values to use a remote PR
+      service.
+
+   :term:`PV`
+      The version of the recipe.
+
+   :term:`RDEPENDS`
+      Lists a package's runtime dependencies (i.e. other packages) that
+      must be installed in order for the built package to run correctly. If
+      a package in this list cannot be found during the build, you will get
+      a build error.
+
+      Because the ``RDEPENDS`` variable applies to packages being built,
+      you should always use the variable in a form with an attached package
+      name. For example, suppose you are building a development package
+      that depends on the ``perl`` package. In this case, you would use the
+      following ``RDEPENDS`` statement: ::
+
+         RDEPENDS_${PN}-dev += "perl"
+
+      In the example, the development package depends on the ``perl`` package.
+      Thus, the ``RDEPENDS`` variable has the ``${PN}-dev`` package name as part
+      of the variable.
+
+      BitBake supports specifying versioned dependencies. Although the
+      syntax varies depending on the packaging format, BitBake hides these
+      differences from you. Here is the general syntax to specify versions
+      with the ``RDEPENDS`` variable: ::
+
+         RDEPENDS_${PN} = "package (operator version)"
+
+      For ``operator``, you can specify the following: ::
+
+         =
+         <
+         >
+         <=
+         >=
+
+      For example, the following sets up a dependency on version 1.2 or
+      greater of the package ``foo``: ::
+
+         RDEPENDS_${PN} = "foo (>= 1.2)"
+
+      For information on build-time dependencies, see the :term:`DEPENDS`
+      variable.
+
+   :term:`REPODIR`
+      The directory in which a local copy of a ``google-repo`` directory is
+      stored when it is synced.
+
+   :term:`REQUIRED_VERSION`
+      If there are multiple versions of a recipe available, this variable
+      determines which version should be given preference. ``REQUIRED_VERSION``
+      works in exactly the same manner as :term:`PREFERRED_VERSION`, except
+      that if the specified version is not available then an error message
+      is shown and the build fails immediately.
+
+      If both ``REQUIRED_VERSION`` and ``PREFERRED_VERSION`` are set for
+      the same recipe, the ``REQUIRED_VERSION`` value applies.
+
+   :term:`RPROVIDES`
+      A list of package name aliases that a package also provides. These
+      aliases are useful for satisfying runtime dependencies of other
+      packages both during the build and on the target (as specified by
+      ``RDEPENDS``).
+
+      As with all package-controlling variables, you must always use the
+      variable in conjunction with a package name override. Here is an
+      example: ::
+
+         RPROVIDES_${PN} = "widget-abi-2"
+
+   :term:`RRECOMMENDS`
+      A list of packages that extends the usability of a package being
+      built. The package being built does not depend on this list of
+      packages in order to successfully build, but needs them for the
+      extended usability. To specify runtime dependencies for packages, see
+      the ``RDEPENDS`` variable.
+
+      BitBake supports specifying versioned recommends. Although the syntax
+      varies depending on the packaging format, BitBake hides these
+      differences from you. Here is the general syntax to specify versions
+      with the ``RRECOMMENDS`` variable: ::
+
+         RRECOMMENDS_${PN} = "package (operator version)"
+
+      For ``operator``, you can specify the following: ::
+
+         =
+         <
+         >
+         <=
+         >=
+
+      For example, the following sets up a recommend on version
+      1.2 or greater of the package ``foo``: ::
+
+         RRECOMMENDS_${PN} = "foo (>= 1.2)"
+
+   :term:`SECTION`
+      The section in which packages should be categorized.
+
+   :term:`SRC_URI`
+      The list of source files - local or remote. This variable tells
+      BitBake which bits to pull for the build and how to pull them. For
+      example, if the recipe or append file needs to fetch a single tarball
+      from the Internet, the recipe or append file uses a ``SRC_URI`` entry
+      that specifies that tarball. On the other hand, if the recipe or
+      append file needs to fetch a tarball and include a custom file, the
+      recipe or append file needs an ``SRC_URI`` variable that specifies
+      all those sources.
+
+      The following list explains the available URI protocols:
+
+      -  ``file://`` : Fetches files, which are usually files shipped
+         with the metadata, from the local machine. The path is relative to
+         the :term:`FILESPATH` variable.
+
+      -  ``bzr://`` : Fetches files from a Bazaar revision control
+         repository.
+
+      -  ``git://`` : Fetches files from a Git revision control
+         repository.
+
+      -  ``osc://`` : Fetches files from an OSC (OpenSUSE Build service)
+         revision control repository.
+
+      -  ``repo://`` : Fetches files from a repo (Git) repository.
+
+      -  ``http://`` : Fetches files from the Internet using HTTP.
+
+      -  ``https://`` : Fetches files from the Internet using HTTPS.
+
+      -  ``ftp://`` : Fetches files from the Internet using FTP.
+
+      -  ``cvs://`` : Fetches files from a CVS revision control
+         repository.
+
+      -  ``hg://`` : Fetches files from a Mercurial (``hg``) revision
+         control repository.
+
+      -  ``p4://`` : Fetches files from a Perforce (``p4``) revision
+         control repository.
+
+      -  ``ssh://`` : Fetches files from a secure shell.
+
+      -  ``svn://`` : Fetches files from a Subversion (``svn``) revision
+         control repository.
+
+      -  ``az://`` : Fetches files from an Azure Storage account using HTTPS.
+
+      Here are some additional options worth mentioning:
+
+      -  ``unpack`` : Controls whether or not to unpack the file if it is
+         an archive. The default action is to unpack the file.
+
+      -  ``subdir`` : Places the file (or extracts its contents) into the
+         specified subdirectory. This option is useful for unusual tarballs
+         or other archives that do not have their files already in a
+         subdirectory within the archive.
+
+      -  ``name`` : Specifies a name to be used for association with
+         ``SRC_URI`` checksums when you have more than one file specified
+         in ``SRC_URI``.
+
+      -  ``downloadfilename`` : Specifies the filename used when storing
+         the downloaded file.
+
+   :term:`SRCDATE`
+      The date of the source code used to build the package. This variable
+      applies only if the source was fetched from a Source Code Manager
+      (SCM).
+
+   :term:`SRCREV`
+      The revision of the source code used to build the package. This
+      variable applies only when using Subversion, Git, Mercurial and
+      Bazaar. If you want to build a fixed revision and you want to avoid
+      performing a query on the remote repository every time BitBake parses
+      your recipe, you should specify a ``SRCREV`` that is a full revision
+      identifier and not just a tag.
+
+   :term:`SRCREV_FORMAT`
+      Helps construct valid :term:`SRCREV` values when
+      multiple source controlled URLs are used in
+      :term:`SRC_URI`.
+
+      The system needs help constructing these values under these
+      circumstances. Each component in the ``SRC_URI`` is assigned a name
+      and these are referenced in the ``SRCREV_FORMAT`` variable. Consider
+      an example with URLs named "machine" and "meta". In this case,
+      ``SRCREV_FORMAT`` could look like "machine_meta" and those names
+      would have the SCM versions substituted into each position. Only one
+      ``AUTOINC`` placeholder is added and if needed. And, this placeholder
+      is placed at the start of the returned string.
+
+   :term:`STAMP`
+      Specifies the base path used to create recipe stamp files. The path
+      to an actual stamp file is constructed by evaluating this string and
+      then appending additional information.
+
+   :term:`STAMPCLEAN`
+      Specifies the base path used to create recipe stamp files. Unlike the
+      :term:`STAMP` variable, ``STAMPCLEAN`` can contain
+      wildcards to match the range of files a clean operation should
+      remove. BitBake uses a clean operation to remove any other stamps it
+      should be removing when creating a new stamp.
+
+   :term:`SUMMARY`
+      A short summary for the recipe, which is 72 characters or less.
+
+   :term:`SVNDIR`
+      The directory in which files checked out of a Subversion system are
+      stored.
+
+   :term:`T`
+      Points to a directory were BitBake places temporary files, which
+      consist mostly of task logs and scripts, when building a particular
+      recipe.
+
+   :term:`TOPDIR`
+      Points to the build directory. BitBake automatically sets this
+      variable.
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
deleted file mode 100644
index c4bd1f25..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
+++ /dev/null
@@ -1,2476 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
-[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
-
-<!-- Dummy chapter -->
-<chapter id='ref-bb-variables-glos'>
-
-<title>Variables Glossary</title>
-
-<para>
-    This chapter lists common variables used by BitBake and gives an overview
-    of their function and contents.
-</para>
-
-<note>
-    Following are some points regarding the variables listed in this glossary:
-    <itemizedlist>
-        <listitem><para>The variables listed in this glossary
-            are specific to BitBake.
-            Consequently, the descriptions are limited to that context.
-            </para></listitem>
-        <listitem><para>Also, variables exist in other systems that use BitBake
-            (e.g. The Yocto Project and OpenEmbedded) that have names identical
-            to those found in this glossary.
-            For such cases, the variables in those systems extend the
-            functionality of the variable as it is described here in
-            this glossary.
-            </para></listitem>
-        <listitem><para>Finally, there are variables mentioned in this
-            glossary that do not appear in the BitBake glossary.
-            These other variables are variables used in systems that use
-            BitBake.
-            </para></listitem>
-    </itemizedlist>
-</note>
-
-<glossary id='ref-bb-variables-glossary'>
-
-    <para>
-       <link linkend='var-bb-ASSUME_PROVIDED'>A</link>
-       <link linkend='var-bb-B'>B</link>
-       <link linkend='var-bb-CACHE'>C</link>
-       <link linkend='var-bb-DEFAULT_PREFERENCE'>D</link>
-       <link linkend='var-bb-EXCLUDE_FROM_WORLD'>E</link>
-       <link linkend='var-bb-FAKEROOT'>F</link>
-       <link linkend='var-bb-GITDIR'>G</link>
-       <link linkend='var-bb-HGDIR'>H</link>
-       <link linkend='var-bb-INHERIT'>I</link>
-<!--               <link linkend='var-glossary-j'>J</link> -->
-<!--       <link linkend='var-KARCH'>K</link> -->
-       <link linkend='var-bb-LAYERDEPENDS'>L</link>
-       <link linkend='var-bb-MIRRORS'>M</link>
-<!--               <link linkend='var-glossary-n'>N</link> -->
-       <link linkend='var-bb-OVERRIDES'>O</link>
-       <link linkend='var-bb-P4DIR'>P</link>
-<!--       <link linkend='var-QMAKE_PROFILES'>Q</link> -->
-       <link linkend='var-bb-RDEPENDS'>R</link>
-       <link linkend='var-bb-SECTION'>S</link>
-       <link linkend='var-bb-T'>T</link>
-<!--       <link linkend='var-UBOOT_CONFIG'>U</link> -->
-<!--               <link linkend='var-glossary-v'>V</link> -->
-<!--       <link linkend='var-WARN_QA'>W</link> -->
-<!--               <link linkend='var-glossary-x'>X</link> -->
-<!--               <link linkend='var-glossary-y'>Y</link> -->
-<!--               <link linkend='var-glossary-z'>Z</link>-->
-    </para>
-
-    <glossdiv id='var-bb-glossary-a'><title>A</title>
-
-        <glossentry id='var-bb-ASSUME_PROVIDED'><glossterm>ASSUME_PROVIDED</glossterm>
-            <glossdef>
-                <para>
-                    Lists recipe names
-                    (<link linkend='var-bb-PN'><filename>PN</filename></link>
-                    values) BitBake does not attempt to build.
-                    Instead, BitBake assumes these recipes have already been
-                    built.
-                </para>
-
-                <para>
-                    In OpenEmbedded-Core, <filename>ASSUME_PROVIDED</filename>
-                    mostly specifies native tools that should not be built.
-                    An example is <filename>git-native</filename>, which
-                    when specified allows for the Git binary from the host to
-                    be used rather than building
-                    <filename>git-native</filename>.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-
-    <glossdiv id='var-bb-glossary-b'><title>B</title>
-
-        <glossentry id='var-bb-B'><glossterm>B</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which BitBake executes functions
-                    during a recipe's build process.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_ALLOWED_NETWORKS'><glossterm>BB_ALLOWED_NETWORKS</glossterm>
-            <glossdef>
-                <para>
-                    Specifies a space-delimited list of hosts that the fetcher
-                    is allowed to use to obtain the required source code.
-                    Following are considerations surrounding this variable:
-                    <itemizedlist>
-                        <listitem><para>
-                            This host list is only used if
-                            <link linkend='var-bb-BB_NO_NETWORK'><filename>BB_NO_NETWORK</filename></link>
-                            is either not set or set to "0".
-                            </para></listitem>
-                        <listitem><para>
-                            Limited support for the "<filename>*</filename>"
-                            wildcard character for matching against the
-                            beginning of host names exists.
-                            For example, the following setting matches
-                            <filename>git.gnu.org</filename>,
-                            <filename>ftp.gnu.org</filename>, and
-                            <filename>foo.git.gnu.org</filename>.
-                            <literallayout class='monospaced'>
-     BB_ALLOWED_NETWORKS = "*.gnu.org"
-                            </literallayout>
-                            <note><title>Important</title>
-                                <para>The use of the "<filename>*</filename>"
-                                character only works at the beginning of
-                                a host name and it must be isolated from
-                                the remainder of the host name.
-                                You cannot use the wildcard character in any
-                                other location of the name or combined with
-                                the front part of the name.</para>
-
-                                <para>For example,
-                                <filename>*.foo.bar</filename> is supported,
-                                while <filename>*aa.foo.bar</filename> is not.
-                                </para>
-                            </note>
-                            </para></listitem>
-                        <listitem><para>
-                            Mirrors not in the host list are skipped and
-                            logged in debug.
-                            </para></listitem>
-                        <listitem><para>
-                            Attempts to access networks not in the host list
-                            cause a failure.
-                            </para></listitem>
-                    </itemizedlist>
-                    Using <filename>BB_ALLOWED_NETWORKS</filename> in
-                    conjunction with
-                    <link linkend='var-bb-PREMIRRORS'><filename>PREMIRRORS</filename></link>
-                    is very useful.
-                    Adding the host you want to use to
-                    <filename>PREMIRRORS</filename> results in the source code
-                    being fetched from an allowed location and avoids raising
-                    an error when a host that is not allowed is in a
-                    <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
-                    statement.
-                    This is because the fetcher does not attempt to use the
-                    host listed in <filename>SRC_URI</filename> after a
-                    successful fetch from the
-                    <filename>PREMIRRORS</filename> occurs.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_CONSOLELOG'><glossterm>BB_CONSOLELOG</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the path to a log file into which BitBake's user
-                    interface writes output during the build.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_CURRENTTASK'><glossterm>BB_CURRENTTASK</glossterm>
-            <glossdef>
-                <para>
-                    Contains the name of the currently running task.
-                    The name does not include the
-                    <filename>do_</filename> prefix.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_DANGLINGAPPENDS_WARNONLY'><glossterm>BB_DANGLINGAPPENDS_WARNONLY</glossterm>
-            <glossdef>
-                <para>
-                    Defines how BitBake handles situations where an append
-                    file (<filename>.bbappend</filename>) has no
-                    corresponding recipe file (<filename>.bb</filename>).
-                    This condition often occurs when layers get out of sync
-                    (e.g. <filename>oe-core</filename> bumps a
-                    recipe version and the old recipe no longer exists and the
-                    other layer has not been updated to the new version
-                    of the recipe yet).
-                </para>
-
-                <para>
-                    The default fatal behavior is safest because it is
-                    the sane reaction given something is out of sync.
-                    It is important to realize when your changes are no longer
-                    being applied.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_DEFAULT_TASK'><glossterm>BB_DEFAULT_TASK</glossterm>
-            <glossdef>
-                <para>
-                    The default task to use when none is specified (e.g.
-                    with the <filename>-c</filename> command line option).
-                    The task name specified should not include the
-                    <filename>do_</filename> prefix.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_DISKMON_DIRS'><glossterm>BB_DISKMON_DIRS</glossterm>
-            <glossdef>
-                <para>
-                    Monitors disk space and available inodes during the build
-                    and allows you to control the build based on these
-                    parameters.
-                </para>
-
-                <para>
-                    Disk space monitoring is disabled by default.
-                    When setting this variable, use the following form:
-                    <literallayout class='monospaced'>
-     BB_DISKMON_DIRS = "&lt;action&gt;,&lt;dir&gt;,&lt;threshold&gt; [...]"
-
-     where:
-
-        &lt;action&gt; is:
-           ABORT:     Immediately abort the build when
-                      a threshold is broken.
-           STOPTASKS: Stop the build after the currently
-                      executing tasks have finished when
-                      a threshold is broken.
-           WARN:      Issue a warning but continue the
-                      build when a threshold is broken.
-                      Subsequent warnings are issued as
-                      defined by the
-                      <link linkend='var-bb-BB_DISKMON_WARNINTERVAL'>BB_DISKMON_WARNINTERVAL</link> variable,
-                      which must be defined.
-
-        &lt;dir&gt; is:
-           Any directory you choose. You can specify one or
-           more directories to monitor by separating the
-           groupings with a space.  If two directories are
-           on the same device, only the first directory
-           is monitored.
-
-        &lt;threshold&gt; is:
-           Either the minimum available disk space,
-           the minimum number of free inodes, or
-           both.  You must specify at least one.  To
-           omit one or the other, simply omit the value.
-           Specify the threshold using G, M, K for Gbytes,
-           Mbytes, and Kbytes, respectively. If you do
-           not specify G, M, or K, Kbytes is assumed by
-           default.  Do not use GB, MB, or KB.
-                    </literallayout>
-                </para>
-
-                <para>
-                    Here are some examples:
-                    <literallayout class='monospaced'>
-     BB_DISKMON_DIRS = "ABORT,${TMPDIR},1G,100K WARN,${SSTATE_DIR},1G,100K"
-     BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},1G"
-     BB_DISKMON_DIRS = "ABORT,${TMPDIR},,100K"
-                    </literallayout>
-                    The first example works only if you also set
-                    the <link linkend='var-bb-BB_DISKMON_WARNINTERVAL'><filename>BB_DISKMON_WARNINTERVAL</filename></link> variable.
-                    This example causes the build system to immediately
-                    abort when either the disk space in <filename>${TMPDIR}</filename> drops
-                    below 1 Gbyte or the available free inodes drops below
-                    100 Kbytes.
-                    Because two directories are provided with the variable, the
-                    build system also issues a
-                    warning when the disk space in the
-                    <filename>${SSTATE_DIR}</filename> directory drops
-                    below 1 Gbyte or the number of free inodes drops
-                    below 100 Kbytes.
-                    Subsequent warnings are issued during intervals as
-                    defined by the <filename>BB_DISKMON_WARNINTERVAL</filename>
-                    variable.
-                </para>
-
-                <para>
-                    The second example stops the build after all currently
-                    executing tasks complete when the minimum disk space
-                    in the <filename>${TMPDIR}</filename>
-                    directory drops below 1 Gbyte.
-                    No disk monitoring occurs for the free inodes in this case.
-                </para>
-
-                <para>
-                    The final example immediately aborts the build when the
-                    number of free inodes in the <filename>${TMPDIR}</filename> directory
-                    drops below 100 Kbytes.
-                    No disk space monitoring for the directory itself occurs
-                    in this case.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_DISKMON_WARNINTERVAL'><glossterm>BB_DISKMON_WARNINTERVAL</glossterm>
-            <glossdef>
-                <para>
-                    Defines the disk space and free inode warning intervals.
-                </para>
-
-                <para>
-                    If you are going to use the
-                    <filename>BB_DISKMON_WARNINTERVAL</filename> variable, you must
-                    also use the
-                    <link linkend='var-bb-BB_DISKMON_DIRS'><filename>BB_DISKMON_DIRS</filename></link> variable
-                    and define its action as "WARN".
-                    During the build, subsequent warnings are issued each time
-                    disk space or number of free inodes further reduces by
-                    the respective interval.
-                </para>
-
-                <para>
-                    If you do not provide a <filename>BB_DISKMON_WARNINTERVAL</filename>
-                    variable and you do use <filename>BB_DISKMON_DIRS</filename> with
-                    the "WARN" action, the disk monitoring interval defaults to
-                    the following:
-                    <literallayout class='monospaced'>
-     BB_DISKMON_WARNINTERVAL = "50M,5K"
-                    </literallayout>
-                </para>
-
-                <para>
-                    When specifying the variable in your configuration file,
-                    use the following form:
-                    <literallayout class='monospaced'>
-     BB_DISKMON_WARNINTERVAL = "&lt;disk_space_interval&gt;,&lt;disk_inode_interval&gt;"
-
-     where:
-
-        &lt;disk_space_interval&gt; is:
-           An interval of memory expressed in either
-           G, M, or K for Gbytes, Mbytes, or Kbytes,
-           respectively. You cannot use GB, MB, or KB.
-
-        &lt;disk_inode_interval&gt; is:
-           An interval of free inodes expressed in either
-           G, M, or K for Gbytes, Mbytes, or Kbytes,
-           respectively. You cannot use GB, MB, or KB.
-                    </literallayout>
-                </para>
-
-                <para>
-                    Here is an example:
-                    <literallayout class='monospaced'>
-     BB_DISKMON_DIRS = "WARN,${SSTATE_DIR},1G,100K"
-     BB_DISKMON_WARNINTERVAL = "50M,5K"
-                    </literallayout>
-                    These variables cause BitBake to
-                    issue subsequent warnings each time the available
-                    disk space further reduces by 50 Mbytes or the number
-                    of free inodes further reduces by 5 Kbytes in the
-                    <filename>${SSTATE_DIR}</filename> directory.
-                    Subsequent warnings based on the interval occur each time
-                    a respective interval is reached beyond the initial warning
-                    (i.e. 1 Gbytes and 100 Kbytes).
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_ENV_WHITELIST'><glossterm>BB_ENV_WHITELIST</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the internal whitelist of variables to allow
-                    through from the external environment into BitBake's
-                    datastore.
-                    If the value of this variable is not specified
-                    (which is the default), the following list is used:
-                    <link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>,
-                    <link linkend='var-bb-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>,
-                    <link linkend='var-bb-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>,
-                    and
-                    <link linkend='var-bb-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>.
-                    <note>
-                        You must set this variable in the external environment
-                        in order for it to work.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_ENV_EXTRAWHITE'><glossterm>BB_ENV_EXTRAWHITE</glossterm>
-            <glossdef>
-                <para>
-                    Specifies an additional set of variables to allow through
-                    (whitelist) from the external environment into BitBake's
-                    datastore.
-                    This list of variables are on top of the internal list
-                    set in
-                    <link linkend='var-bb-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>.
-                    <note>
-                        You must set this variable in the external
-                        environment in order for it to work.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_FETCH_PREMIRRORONLY'><glossterm>BB_FETCH_PREMIRRORONLY</glossterm>
-            <glossdef>
-                <para>
-                    When set to "1", causes BitBake's fetcher module to only
-                    search
-                    <link linkend='var-bb-PREMIRRORS'><filename>PREMIRRORS</filename></link>
-                    for files.
-                    BitBake will not search the main
-                    <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
-                    or
-                    <link linkend='var-bb-MIRRORS'><filename>MIRRORS</filename></link>.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_FILENAME'><glossterm>BB_FILENAME</glossterm>
-            <glossdef>
-                <para>
-                    Contains the filename of the recipe that owns the currently
-                    running task.
-                    For example, if the <filename>do_fetch</filename> task that
-                    resides in the <filename>my-recipe.bb</filename> is
-                    executing, the <filename>BB_FILENAME</filename> variable
-                    contains "/foo/path/my-recipe.bb".
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_GENERATE_MIRROR_TARBALLS'><glossterm>BB_GENERATE_MIRROR_TARBALLS</glossterm>
-            <glossdef>
-                <para>
-                    Causes tarballs of the Git repositories, including the
-                    Git metadata, to be placed in the
-                    <link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
-                    directory.
-                    Anyone wishing to create a source mirror would want to
-                    enable this variable.
-                </para>
-
-                <para>
-                    For performance reasons, creating and placing tarballs of
-                    the Git repositories is not the default action by BitBake.
-                    <literallayout class='monospaced'>
-     BB_GENERATE_MIRROR_TARBALLS = "1"
-                    </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_HASHCONFIG_WHITELIST'><glossterm>BB_HASHCONFIG_WHITELIST</glossterm>
-            <glossdef>
-                <para>
-                    Lists variables that are excluded from base configuration
-                    checksum, which is used to determine if the cache can
-                    be reused.
-                </para>
-
-                <para>
-                    One of the ways BitBake determines whether to re-parse the
-                    main metadata is through checksums of the variables in the
-                    datastore of the base configuration data.
-                    There are variables that you typically want to exclude when
-                    checking whether or not to re-parse and thus rebuild the
-                    cache.
-                    As an example, you would usually exclude
-                    <filename>TIME</filename> and <filename>DATE</filename>
-                    because these variables are always changing.
-                    If you did not exclude them, BitBake would never reuse the
-                    cache.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_HASHBASE_WHITELIST'><glossterm>BB_HASHBASE_WHITELIST</glossterm>
-            <glossdef>
-                <para>
-                    Lists variables that are excluded from checksum and
-                    dependency data.
-                    Variables that are excluded can therefore change without
-                    affecting the checksum mechanism.
-                    A common example would be the variable for the path of
-                    the build.
-                    BitBake's output should not (and usually does not) depend
-                    on the directory in which it was built.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_HASHCHECK_FUNCTION'><glossterm>BB_HASHCHECK_FUNCTION</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the name of the function to call during the
-                    "setscene" part of the task's execution in order to
-                    validate the list of task hashes.
-                    The function returns the list of setscene tasks that should
-                    be executed.
-                </para>
-
-                <para>
-                    At this point in the execution of the code, the objective
-                    is to quickly verify if a given setscene function is likely
-                    to work or not.
-                    It's easier to check the list of setscene functions in
-                    one pass than to call many individual tasks.
-                    The returned list need not be completely accurate.
-                    A given setscene task can still later fail.
-                    However, the more accurate the data returned, the more
-                    efficient the build will be.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_INVALIDCONF'><glossterm>BB_INVALIDCONF</glossterm>
-            <glossdef>
-                <para>
-                    Used in combination with the
-                    <filename>ConfigParsed</filename> event to trigger
-                    re-parsing the base metadata (i.e. all the
-                    recipes).
-                    The <filename>ConfigParsed</filename> event can set the
-                    variable to trigger the re-parse.
-                    You must be careful to avoid recursive loops with this
-                    functionality.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_LOGCONFIG'><glossterm>BB_LOGCONFIG</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the name of a config file that contains the user
-                    logging configuration. See
-                    <link linkend="logging">Logging</link> for additional
-                    information
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_LOGFMT'><glossterm>BB_LOGFMT</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the name of the log files saved into
-                    <filename>${</filename><link linkend='var-bb-T'><filename>T</filename></link><filename>}</filename>.
-                    By default, the <filename>BB_LOGFMT</filename> variable
-                    is undefined and the log file names get created using the
-                    following form:
-                    <literallayout class='monospaced'>
-     log.{task}.{pid}
-                    </literallayout>
-                    If you want to force log files to take a specific name,
-                    you can set this variable in a configuration file.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_NICE_LEVEL'><glossterm>BB_NICE_LEVEL</glossterm>
-            <glossdef>
-                <para>
-                    Allows BitBake to run at a specific priority
-                    (i.e. nice level).
-                    System permissions usually mean that BitBake can reduce its
-                    priority but not raise it again.
-                    See
-                    <link linkend='var-bb-BB_TASK_NICE_LEVEL'><filename>BB_TASK_NICE_LEVEL</filename></link>
-                    for additional information.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_NO_NETWORK'><glossterm>BB_NO_NETWORK</glossterm>
-            <glossdef>
-                <para>
-                    Disables network access in the BitBake fetcher modules.
-                    With this access disabled, any command that attempts to
-                    access the network becomes an error.
-                </para>
-
-                <para>
-                    Disabling network access is useful for testing source
-                    mirrors, running builds when not connected to the Internet,
-                    and when operating in certain kinds of firewall
-                    environments.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_NUMBER_THREADS'><glossterm>BB_NUMBER_THREADS</glossterm>
-            <glossdef>
-                <para>
-                    The maximum number of tasks BitBake should run in parallel
-                    at any one time.
-                    If your host development system supports multiple cores,
-                    a good rule of thumb is to set this variable to twice the
-                    number of cores.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_NUMBER_PARSE_THREADS'><glossterm>BB_NUMBER_PARSE_THREADS</glossterm>
-            <glossdef>
-                <para>
-                    Sets the number of threads BitBake uses when parsing.
-                    By default, the number of threads is equal to the number
-                    of cores on the system.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_ORIGENV'><glossterm>BB_ORIGENV</glossterm>
-            <glossdef>
-                <para>
-                    Contains a copy of the original external environment in
-                    which BitBake was run.
-                    The copy is taken before any whitelisted variable values
-                    are filtered into BitBake's datastore.
-                    <note>
-                        The contents of this variable is a datastore object
-                        that can be queried using the normal datastore
-                        operations.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_PRESERVE_ENV'><glossterm>BB_PRESERVE_ENV</glossterm>
-            <glossdef>
-                <para>
-                    Disables whitelisting and instead allows all variables
-                    through from the external environment into BitBake's
-                    datastore.
-                    <note>
-                        You must set this variable in the external
-                        environment in order for it to work.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_RUNFMT'><glossterm>BB_RUNFMT</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the name of the executable script files
-                    (i.e. run files) saved into
-                    <filename>${</filename><link linkend='var-bb-T'><filename>T</filename></link><filename>}</filename>.
-                    By default, the <filename>BB_RUNFMT</filename> variable
-                    is undefined and the run file names get created using the
-                    following form:
-                    <literallayout class='monospaced'>
-     run.{task}.{pid}
-                    </literallayout>
-                    If you want to force run files to take a specific name,
-                    you can set this variable in a configuration file.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_RUNTASK'><glossterm>BB_RUNTASK</glossterm>
-            <glossdef>
-                <para>
-                    Contains the name of the currently executing task.
-                    The value includes the "do_" prefix.
-                    For example, if the currently executing task is
-                    <filename>do_config</filename>, the value is
-                    "do_config".
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SCHEDULER'><glossterm>BB_SCHEDULER</glossterm>
-            <glossdef>
-                <para>
-                    Selects the name of the scheduler to use for the
-                    scheduling of BitBake tasks.
-                    Three options exist:
-                    <itemizedlist>
-                        <listitem><para><emphasis>basic</emphasis> -
-                            The basic framework from which everything derives.
-                            Using this option causes tasks to be ordered
-                            numerically as they are parsed.
-                            </para></listitem>
-                        <listitem><para><emphasis>speed</emphasis> -
-                            Executes tasks first that have more tasks
-                            depending on them.
-                            The "speed" option is the default.
-                            </para></listitem>
-                        <listitem><para><emphasis>completion</emphasis> -
-                            Causes the scheduler to try to complete a given
-                            recipe once its build has started.
-                            </para></listitem>
-                    </itemizedlist>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SCHEDULERS'><glossterm>BB_SCHEDULERS</glossterm>
-            <glossdef>
-                <para>
-                    Defines custom schedulers to import.
-                    Custom schedulers need to be derived from the
-                    <filename>RunQueueScheduler</filename> class.
-                </para>
-
-                <para>
-                    For information how to select a scheduler, see the
-                    <link linkend='var-bb-BB_SCHEDULER'><filename>BB_SCHEDULER</filename></link>
-                    variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SETSCENE_DEPVALID'><glossterm>BB_SETSCENE_DEPVALID</glossterm>
-            <glossdef>
-                <para>
-                    Specifies a function BitBake calls that determines
-                    whether BitBake requires a setscene dependency to be met.
-                </para>
-
-                <para>
-                    When running a setscene task, BitBake needs to
-                    know which dependencies of that setscene task also need
-                    to be run.
-                    Whether dependencies also need to be run is highly
-                    dependent on the metadata.
-                    The function specified by this variable returns a
-                    "True" or "False" depending on whether the dependency needs
-                    to be met.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SETSCENE_VERIFY_FUNCTION2'><glossterm>BB_SETSCENE_VERIFY_FUNCTION2</glossterm>
-            <glossdef>
-                <para>
-                    Specifies a function to call that verifies the list of
-                    planned task execution before the main task execution
-                    happens.
-                    The function is called once BitBake has a list of setscene
-                    tasks that have run and either succeeded or failed.
-                </para>
-
-                <para>
-                    The function allows for a task list check to see if they
-                    make sense.
-                    Even if BitBake was planning to skip a task, the
-                    returned value of the function can force BitBake to run
-                    the task, which is necessary under certain metadata
-                    defined circumstances.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SIGNATURE_EXCLUDE_FLAGS'><glossterm>BB_SIGNATURE_EXCLUDE_FLAGS</glossterm>
-            <glossdef>
-                <para>
-                    Lists variable flags (varflags)
-                    that can be safely excluded from checksum
-                    and dependency data for keys in the datastore.
-                    When generating checksum or dependency data for keys in the
-                    datastore, the flags set against that key are normally
-                    included in the checksum.
-                </para>
-
-                <para>
-                    For more information on varflags, see the
-                    "<link linkend='variable-flags'>Variable Flags</link>"
-                    section.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SIGNATURE_HANDLER'><glossterm>BB_SIGNATURE_HANDLER</glossterm>
-            <glossdef>
-                <para>
-                    Defines the name of the signature handler BitBake uses.
-                    The signature handler defines the way stamp files are
-                    created and handled, if and how the signature is
-                    incorporated into the stamps, and how the signature
-                    itself is generated.
-                </para>
-
-                <para>
-                    A new signature handler can be added by injecting a class
-                    derived from the
-                    <filename>SignatureGenerator</filename> class into the
-                    global namespace.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_SRCREV_POLICY'><glossterm>BB_SRCREV_POLICY</glossterm>
-            <glossdef>
-                <para>
-                    Defines the behavior of the fetcher when it interacts with
-                    source control systems and dynamic source revisions.
-                    The <filename>BB_SRCREV_POLICY</filename> variable is
-                    useful when working without a network.
-                </para>
-
-                <para>
-                    The variable can be set using one of two policies:
-                    <itemizedlist>
-                        <listitem><para><emphasis>cache</emphasis> -
-                            Retains the value the system obtained previously
-                            rather than querying the source control system
-                            each time.
-                            </para></listitem>
-                        <listitem><para><emphasis>clear</emphasis> -
-                            Queries the source controls system every time.
-                            With this policy, there is no cache.
-                            The "clear" policy is the default.
-                            </para></listitem>
-                    </itemizedlist>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_STAMP_POLICY'><glossterm>BB_STAMP_POLICY</glossterm>
-            <glossdef>
-                <para>
-                    Defines the mode used for how timestamps of stamp files
-                    are compared.
-                    You can set the variable to one of the following modes:
-                    <itemizedlist>
-                        <listitem><para><emphasis>perfile</emphasis> -
-                            Timestamp comparisons are only made
-                            between timestamps of a specific recipe.
-                            This is the default mode.
-                            </para></listitem>
-                        <listitem><para><emphasis>full</emphasis> -
-                            Timestamp comparisons are made for all
-                            dependencies.
-                            </para></listitem>
-                        <listitem><para><emphasis>whitelist</emphasis> -
-                            Identical to "full" mode except timestamp
-                            comparisons are made for recipes listed in the
-                            <link linkend='var-bb-BB_STAMP_WHITELIST'><filename>BB_STAMP_WHITELIST</filename></link>
-                            variable.
-                            </para></listitem>
-                    </itemizedlist>
-                    <note>
-                        Stamp policies are largely obsolete with the
-                        introduction of setscene tasks.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_STAMP_WHITELIST'><glossterm>BB_STAMP_WHITELIST</glossterm>
-            <glossdef>
-                <para>
-                    Lists files whose stamp file timestamps are compared when
-                    the stamp policy mode is set to "whitelist".
-                    For information on stamp policies, see the
-                    <link linkend='var-bb-BB_STAMP_POLICY'><filename>BB_STAMP_POLICY</filename></link>
-                    variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_STRICT_CHECKSUM'><glossterm>BB_STRICT_CHECKSUM</glossterm>
-            <glossdef>
-                <para>
-                    Sets a more strict checksum mechanism for non-local URLs.
-                    Setting this variable to a value causes BitBake
-                    to report an error if it encounters a non-local URL
-                    that does not have at least one checksum specified.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_TASK_IONICE_LEVEL'><glossterm>BB_TASK_IONICE_LEVEL</glossterm>
-            <glossdef>
-                <para>
-                    Allows adjustment of a task's Input/Output priority.
-                    During Autobuilder testing, random failures can occur
-                    for tasks due to I/O starvation.
-                    These failures occur during various QEMU runtime timeouts.
-                    You can use the <filename>BB_TASK_IONICE_LEVEL</filename>
-                    variable to adjust the I/O priority of these tasks.
-                    <note>
-                        This variable works similarly to the
-                        <link linkend='var-bb-BB_TASK_NICE_LEVEL'><filename>BB_TASK_NICE_LEVEL</filename></link>
-                        variable except with a task's I/O priorities.
-                    </note>
-                </para>
-
-                <para>
-                    Set the variable as follows:
-                    <literallayout class='monospaced'>
-     BB_TASK_IONICE_LEVEL = "<replaceable>class</replaceable>.<replaceable>prio</replaceable>"
-                    </literallayout>
-                    For <replaceable>class</replaceable>, the default value is
-                    "2", which is a best effort.
-                    You can use "1" for realtime and "3" for idle.
-                    If you want to use realtime, you must have superuser
-                    privileges.
-                </para>
-
-                <para>
-                    For <replaceable>prio</replaceable>, you can use any
-                    value from "0", which is the highest priority, to "7",
-                    which is the lowest.
-                    The default value is "4".
-                    You do not need any special privileges to use this range
-                    of priority values.
-                    <note>
-                        In order for your I/O priority settings to take effect,
-                        you need the Completely Fair Queuing (CFQ) Scheduler
-                        selected for the backing block device.
-                        To select the scheduler, use the following command form
-                        where <replaceable>device</replaceable> is the device
-                        (e.g. sda, sdb, and so forth):
-                        <literallayout class='monospaced'>
-      $ sudo sh -c “echo cfq > /sys/block/<replaceable>device</replaceable>/queu/scheduler
-                        </literallayout>
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_TASK_NICE_LEVEL'><glossterm>BB_TASK_NICE_LEVEL</glossterm>
-            <glossdef>
-                <para>
-                    Allows specific tasks to change their priority
-                    (i.e. nice level).
-                </para>
-
-                <para>
-                    You can use this variable in combination with task
-                    overrides to raise or lower priorities of specific tasks.
-                    For example, on the
-                    <ulink url='http://www.yoctoproject.org'>Yocto Project</ulink>
-                    autobuilder, QEMU emulation in images is given a higher
-                    priority as compared to build tasks to ensure that images
-                    do not suffer timeouts on loaded systems.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_TASKHASH'><glossterm>BB_TASKHASH</glossterm>
-            <glossdef>
-                <para>
-                    Within an executing task, this variable holds the hash
-                    of the task as returned by the currently enabled
-                    signature generator.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_VERBOSE_LOGS'><glossterm>BB_VERBOSE_LOGS</glossterm>
-            <glossdef>
-                <para>
-                    Controls how verbose BitBake is during builds.
-                    If set, shell scripts echo commands and shell script output
-                    appears on standard out (stdout).
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BB_WORKERCONTEXT'><glossterm>BB_WORKERCONTEXT</glossterm>
-            <glossdef>
-                <para>
-                    Specifies if the current context is executing a task.
-                    BitBake sets this variable to "1" when a task is
-                    being executed.
-                    The value is not set when the task is in server context
-                    during parsing or event handling.
-                </para>
-            </glossdef>
-        </glossentry>
-
-
-        <glossentry id='var-bb-BBCLASSEXTEND'><glossterm>BBCLASSEXTEND</glossterm>
-            <glossdef>
-                <para>
-                    Allows you to extend a recipe so that it builds variants
-                    of the software.
-                    Some examples of these variants for recipes from the
-                    OpenEmbedded-Core metadata are "natives" such as
-                    <filename>quilt-native</filename>, which is a copy of
-                    Quilt built to run on the build system; "crosses" such
-                    as <filename>gcc-cross</filename>, which is a compiler
-                    built to run on the build machine but produces binaries
-                    that run on the target <filename>MACHINE</filename>;
-                    "nativesdk", which targets the SDK machine instead of
-                    <filename>MACHINE</filename>; and "mulitlibs" in the form
-                    "<filename>multilib:</filename><replaceable>multilib_name</replaceable>".
-                </para>
-
-                <para>
-                    To build a different variant of the recipe with a minimal
-                    amount of code, it usually is as simple as adding the
-                    variable to your recipe.
-                    Here are two examples.
-                    The "native" variants are from the OpenEmbedded-Core
-                    metadata:
-                    <literallayout class='monospaced'>
-     BBCLASSEXTEND =+ "native nativesdk"
-     BBCLASSEXTEND =+ "multilib:<replaceable>multilib_name</replaceable>"
-                    </literallayout>
-                    <note>
-                        <para>
-                        Internally, the <filename>BBCLASSEXTEND</filename>
-                        mechanism generates recipe variants by rewriting
-                        variable values and applying overrides such as
-                        <filename>_class-native</filename>.
-                        For example, to generate a native version of a recipe,
-                        a
-                        <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                        on "foo" is rewritten to a <filename>DEPENDS</filename>
-                        on "foo-native".
-                        </para>
-
-                        <para>
-                        Even when using <filename>BBCLASSEXTEND</filename>, the
-                        recipe is only parsed once.
-                        Parsing once adds some limitations.
-                        For example, it is not possible to
-                        include a different file depending on the variant,
-                        since <filename>include</filename> statements are
-                        processed when the recipe is parsed.
-                        </para>
-                    </note>
-                </para>
-             </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBDEBUG'><glossterm>BBDEBUG</glossterm>
-            <glossdef>
-                <para>
-                    Sets the BitBake debug output level to a specific value
-                    as incremented by the <filename>-D</filename> command line
-                    option.
-                    <note>
-                        You must set this variable in the external environment
-                        in order for it to work.
-                    </note>
-                </para>
-             </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBFILE_COLLECTIONS'><glossterm>BBFILE_COLLECTIONS</glossterm>
-            <glossdef>
-                <para>Lists the names of configured layers.
-                    These names are used to find the other <filename>BBFILE_*</filename>
-                    variables.
-                    Typically, each layer appends its name to this variable in its
-                    <filename>conf/layer.conf</filename> file.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBFILE_PATTERN'><glossterm>BBFILE_PATTERN</glossterm>
-            <glossdef>
-                <para>Variable that expands to match files from
-                    <link linkend='var-bb-BBFILES'><filename>BBFILES</filename></link>
-                    in a particular layer.
-                    This variable is used in the <filename>conf/layer.conf</filename> file and must
-                    be suffixed with the name of the specific layer (e.g.
-                    <filename>BBFILE_PATTERN_emenlow</filename>).</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBFILE_PRIORITY'><glossterm>BBFILE_PRIORITY</glossterm>
-            <glossdef>
-                <para>Assigns the priority for recipe files in each layer.</para>
-                <para>This variable is useful in situations where the same recipe appears in
-                    more than one layer.
-                    Setting this variable allows you to prioritize a
-                    layer against other layers that contain the same recipe - effectively
-                    letting you control the precedence for the multiple layers.
-                    The precedence established through this variable stands regardless of a
-                    recipe's version
-                    (<link linkend='var-bb-PV'><filename>PV</filename></link> variable).
-                    For example, a layer that has a recipe with a higher <filename>PV</filename> value but for
-                    which the <filename>BBFILE_PRIORITY</filename> is set to have a lower precedence still has a
-                    lower precedence.</para>
-                <para>A larger value for the <filename>BBFILE_PRIORITY</filename> variable results in a higher
-                    precedence.
-                    For example, the value 6 has a higher precedence than the value 5.
-                    If not specified, the <filename>BBFILE_PRIORITY</filename> variable is set based on layer
-                    dependencies (see the
-                    <filename><link linkend='var-bb-LAYERDEPENDS'>LAYERDEPENDS</link></filename> variable for
-                    more information.
-                    The default priority, if unspecified
-                    for a layer with no dependencies, is the lowest defined priority + 1
-                    (or 1 if no priorities are defined).</para>
-                <tip>
-                    You can use the command <filename>bitbake-layers show-layers</filename> to list
-                    all configured layers along with their priorities.
-                </tip>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBFILES'><glossterm>BBFILES</glossterm>
-            <glossdef>
-                <para>
-                    A space-separated list of recipe files BitBake uses to
-                    build software.
-                </para>
-
-                <para>
-                    When specifying recipe files, you can pattern match using
-                    Python's
-                    <ulink url='https://docs.python.org/3/library/glob.html'><filename>glob</filename></ulink>
-                    syntax.
-                    For details on the syntax, see the documentation by
-                    following the previous link.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBINCLUDED'><glossterm>BBINCLUDED</glossterm>
-            <glossdef>
-                <para>
-                    Contains a space-separated list of all of all files that
-                    BitBake's parser included during parsing of the current
-                    file.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBINCLUDELOGS'><glossterm>BBINCLUDELOGS</glossterm>
-            <glossdef>
-                <para>
-                    If set to a value, enables printing the task log when
-                    reporting a failed task.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBINCLUDELOGS_LINES'><glossterm>BBINCLUDELOGS_LINES</glossterm>
-            <glossdef>
-                <para>
-                    If
-                    <link linkend='var-bb-BBINCLUDELOGS'><filename>BBINCLUDELOGS</filename></link>
-                    is set, specifies the maximum number of lines from the
-                    task log file to print when reporting a failed task.
-                    If you do not set <filename>BBINCLUDELOGS_LINES</filename>,
-                    the entire log is printed.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBLAYERS'><glossterm>BBLAYERS</glossterm>
-            <glossdef>
-                <para>Lists the layers to enable during the build.
-                    This variable is defined in the <filename>bblayers.conf</filename> configuration
-                    file in the build directory.
-                    Here is an example:
-                    <literallayout class='monospaced'>
-     BBLAYERS = " \
-       /home/scottrif/poky/meta \
-       /home/scottrif/poky/meta-yocto \
-       /home/scottrif/poky/meta-yocto-bsp \
-       /home/scottrif/poky/meta-mykernel \
-       "
-
-                    </literallayout>
-                    This example enables four layers, one of which is a custom, user-defined layer
-                    named <filename>meta-mykernel</filename>.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBLAYERS_FETCH_DIR'><glossterm>BBLAYERS_FETCH_DIR</glossterm>
-            <glossdef>
-                <para>
-                    Sets the base location where layers are stored.
-                    This setting is used in conjunction with
-                    <filename>bitbake-layers layerindex-fetch</filename> and
-                    tells <filename>bitbake-layers</filename> where to place
-                    the fetched layers.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBMASK'><glossterm>BBMASK</glossterm>
-            <glossdef>
-                <para>
-                    Prevents BitBake from processing recipes and recipe
-                    append files.
-                </para>
-
-                <para>
-                    You can use the <filename>BBMASK</filename> variable
-                    to "hide" these <filename>.bb</filename> and
-                    <filename>.bbappend</filename> files.
-                    BitBake ignores any recipe or recipe append files that
-                    match any of the expressions.
-                    It is as if BitBake does not see them at all.
-                    Consequently, matching files are not parsed or otherwise
-                    used by BitBake.
-                </para>
-
-                <para>
-                    The values you provide are passed to Python's regular
-                    expression compiler.
-                    Consequently, the syntax follows Python's Regular
-                    Expression (re) syntax.
-                    The expressions are compared against the full paths to
-                    the files.
-                    For complete syntax information, see Python's
-                    documentation at
-                    <ulink url='http://docs.python.org/3/library/re.html#re'></ulink>.
-                </para>
-
-                <para>
-                    The following example uses a complete regular expression
-                    to tell BitBake to ignore all recipe and recipe append
-                    files in the <filename>meta-ti/recipes-misc/</filename>
-                    directory:
-                    <literallayout class='monospaced'>
-     BBMASK = "meta-ti/recipes-misc/"
-                    </literallayout>
-                    If you want to mask out multiple directories or recipes,
-                    you can specify multiple regular expression fragments.
-                    This next example masks out multiple directories and
-                    individual recipes:
-                    <literallayout class='monospaced'>
-     BBMASK += "/meta-ti/recipes-misc/ meta-ti/recipes-ti/packagegroup/"
-     BBMASK += "/meta-oe/recipes-support/"
-     BBMASK += "/meta-foo/.*/openldap"
-     BBMASK += "opencv.*\.bbappend"
-     BBMASK += "lzma"
-                    </literallayout>
-                    <note>
-                        When specifying a directory name, use the trailing
-                        slash character to ensure you match just that directory
-                        name.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBMULTICONFIG'><glossterm>BBMULTICONFIG</glossterm>
-            <info>
-                BBMULTICONFIG[doc] = "Enables BitBake to perform multiple configuration builds and lists each separate configuration (multiconfig)."
-            </info>
-            <glossdef>
-                <para role="glossdeffirst">
-<!--                <para role="glossdeffirst"><imagedata fileref="figures/define-generic.png" /> -->
-                    Enables BitBake to perform multiple configuration builds
-                    and lists each separate configuration (multiconfig).
-                    You can use this variable to cause BitBake to build
-                    multiple targets where each target has a separate
-                    configuration.
-                    Define <filename>BBMULTICONFIG</filename> in your
-                    <filename>conf/local.conf</filename> configuration file.
-                </para>
-
-                <para>
-                    As an example, the following line specifies three
-                    multiconfigs, each having a separate configuration file:
-                    <literallayout class='monospaced'>
-     BBMULTIFONFIG = "configA configB configC"
-                    </literallayout>
-                    Each configuration file you use must reside in the
-                    build directory within a directory named
-                    <filename>conf/multiconfig</filename> (e.g.
-                    <replaceable>build_directory</replaceable><filename>/conf/multiconfig/configA.conf</filename>).
-                </para>
-
-                <para>
-                    For information on how to use
-                    <filename>BBMULTICONFIG</filename> in an environment that
-                    supports building targets with multiple configurations,
-                    see the
-                    "<link linkend='executing-a-multiple-configuration-build'>Executing a Multiple Configuration Build</link>"
-                    section.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBPATH'><glossterm>BBPATH</glossterm>
-            <glossdef>
-                <para>
-                    Used by BitBake to locate class
-                    (<filename>.bbclass</filename>) and configuration
-                    (<filename>.conf</filename>) files.
-                    This variable is analogous to the
-                    <filename>PATH</filename> variable.
-                </para>
-
-                <para>
-                    If you run BitBake from a directory outside of the
-                    build directory,
-                    you must be sure to set
-                    <filename>BBPATH</filename> to point to the
-                    build directory.
-                    Set the variable as you would any environment variable
-                    and then run BitBake:
-                    <literallayout class='monospaced'>
-     $ BBPATH="<replaceable>build_directory</replaceable>"
-     $ export BBPATH
-     $ bitbake <replaceable>target</replaceable>
-                    </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBSERVER'><glossterm>BBSERVER</glossterm>
-            <glossdef>
-                <para>
-                    Points to the server that runs memory-resident BitBake.
-                    The variable is only used when you employ memory-resident
-                    BitBake.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBTARGETS'><glossterm>BBTARGETS</glossterm>
-            <glossdef>
-                <para>
-                    Allows you to use a configuration file to add to the list
-                    of command-line target recipes you want to build.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BBVERSIONS'><glossterm>BBVERSIONS</glossterm>
-            <glossdef>
-                <para>
-                    Allows a single recipe to build multiple versions of a
-                    project from a single recipe file.
-                    You also able to specify conditional metadata
-                    using the
-                    <link linkend='var-bb-OVERRIDES'><filename>OVERRIDES</filename></link>
-                    mechanism for a single version or for an optionally named
-                    range of versions.
-                </para>
-
-                <para>
-                    For more information on <filename>BBVERSIONS</filename>,
-                    see the
-                    "<link linkend='variants-class-extension-mechanism'>Variants - Class Extension Mechanism</link>"
-                    section.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BITBAKE_UI'><glossterm>BITBAKE_UI</glossterm>
-            <glossdef>
-                <para>
-                    Used to specify the UI module to use when running BitBake.
-                    Using this variable is equivalent to using the
-                    <filename>-u</filename> command-line option.
-                    <note>
-                        You must set this variable in the external environment
-                        in order for it to work.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BUILDNAME'><glossterm>BUILDNAME</glossterm>
-            <glossdef>
-                <para>
-                    A name assigned to the build.
-                    The name defaults to a datetime stamp of when the build was
-                    started but can be defined by the metadata.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-BZRDIR'><glossterm>BZRDIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which files checked out of a Bazaar
-                    system are stored.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-c'><title>C</title>
-
-        <glossentry id='var-bb-CACHE'><glossterm>CACHE</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the directory BitBake uses to store a cache
-                    of the metadata so it does not need to be parsed every
-                    time BitBake is started.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-CVSDIR'><glossterm>CVSDIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which files checked out under the
-                    CVS system are stored.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-d'><title>D</title>
-
-        <glossentry id='var-bb-DEFAULT_PREFERENCE'><glossterm>DEFAULT_PREFERENCE</glossterm>
-            <glossdef>
-                <para>
-                    Specifies a weak bias for recipe selection priority.
-                </para>
-                <para>
-                    The most common usage of this is variable is to set
-                    it to "-1" within a recipe for a development version of a
-                    piece of software.
-                    Using the variable in this way causes the stable version
-                    of the recipe to build by default in the absence of
-                    <filename><link linkend='var-bb-PREFERRED_VERSION'>PREFERRED_VERSION</link></filename>
-                    being used to build the development version.
-                </para>
-                <note>
-                    The bias provided by <filename>DEFAULT_PREFERENCE</filename>
-                    is weak and is overridden by
-                    <filename><link linkend='var-bb-BBFILE_PRIORITY'>BBFILE_PRIORITY</link></filename>
-                    if that variable is different between two layers
-                    that contain different versions of the same recipe.
-                </note>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-DEPENDS'><glossterm>DEPENDS</glossterm>
-            <glossdef>
-                <para>
-                    Lists a recipe's build-time dependencies
-                    (i.e. other recipe files).
-                </para>
-
-                <para>
-                    Consider this simple example for two recipes named "a" and
-                    "b" that produce similarly named packages.
-                    In this example, the <filename>DEPENDS</filename>
-                    statement appears in the "a" recipe:
-                    <literallayout class='monospaced'>
-     DEPENDS = "b"
-                    </literallayout>
-                    Here, the dependency is such that the
-                    <filename>do_configure</filename> task for recipe "a"
-                    depends on the <filename>do_populate_sysroot</filename>
-                    task of recipe "b".
-                    This means anything that recipe "b" puts into sysroot
-                    is available when recipe "a" is configuring itself.
-                </para>
-
-                <para>
-                    For information on runtime dependencies, see the
-                    <link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>
-                    variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-DESCRIPTION'><glossterm>DESCRIPTION</glossterm>
-            <glossdef>
-                <para>
-                    A long description for the recipe.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-DL_DIR'><glossterm>DL_DIR</glossterm>
-            <glossdef>
-                <para>
-                    The central download directory used by the build process to
-                    store downloads.
-                    By default, <filename>DL_DIR</filename> gets files
-                    suitable for mirroring for everything except Git
-                    repositories.
-                    If you want tarballs of Git repositories, use the
-                    <link linkend='var-bb-BB_GENERATE_MIRROR_TARBALLS'><filename>BB_GENERATE_MIRROR_TARBALLS</filename></link>
-                    variable.
-                </para>
-            </glossdef>
-
-        </glossentry>
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-e'><title>E</title>
-
-        <glossentry id='var-bb-EXCLUDE_FROM_WORLD'><glossterm>EXCLUDE_FROM_WORLD</glossterm>
-            <glossdef>
-                <para>
-                    Directs BitBake to exclude a recipe from world builds (i.e.
-                    <filename>bitbake world</filename>).
-                    During world builds, BitBake locates, parses and builds all
-                    recipes found in every layer exposed in the
-                    <filename>bblayers.conf</filename> configuration file.
-                </para>
-
-                <para>
-                    To exclude a recipe from a world build using this variable,
-                    set the variable to "1" in the recipe.
-                </para>
-
-                <note>
-                    Recipes added to <filename>EXCLUDE_FROM_WORLD</filename>
-                    may still be built during a world build in order to satisfy
-                    dependencies of other recipes.
-                    Adding a recipe to <filename>EXCLUDE_FROM_WORLD</filename>
-                    only ensures that the recipe is not explicitly added
-                    to the list of build targets in a world build.
-                </note>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-f'><title>F</title>
-
-        <glossentry id='var-bb-FAKEROOT'><glossterm>FAKEROOT</glossterm>
-            <glossdef>
-                <para>
-                     Contains the command to use when running a shell script
-                     in a fakeroot environment.
-                     The <filename>FAKEROOT</filename> variable is obsolete
-                     and has been replaced by the other
-                     <filename>FAKEROOT*</filename> variables.
-                     See these entries in the glossary for more information.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FAKEROOTBASEENV'><glossterm>FAKEROOTBASEENV</glossterm>
-            <glossdef>
-                <para>
-                     Lists environment variables to set when executing
-                     the command defined by
-                     <link linkend='var-bb-FAKEROOTCMD'><filename>FAKEROOTCMD</filename></link>
-                     that starts the bitbake-worker process
-                     in the fakeroot environment.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FAKEROOTCMD'><glossterm>FAKEROOTCMD</glossterm>
-            <glossdef>
-                <para>
-                     Contains the command that starts the bitbake-worker
-                     process in the fakeroot environment.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FAKEROOTDIRS'><glossterm>FAKEROOTDIRS</glossterm>
-            <glossdef>
-                <para>
-                     Lists directories to create before running a task in
-                     the fakeroot environment.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FAKEROOTENV'><glossterm>FAKEROOTENV</glossterm>
-            <glossdef>
-                <para>
-                     Lists environment variables to set when running a task
-                     in the fakeroot environment.
-                     For additional information on environment variables and
-                     the fakeroot environment, see the
-                     <link linkend='var-bb-FAKEROOTBASEENV'><filename>FAKEROOTBASEENV</filename></link>
-                     variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FAKEROOTNOENV'><glossterm>FAKEROOTNOENV</glossterm>
-            <glossdef>
-                <para>
-                     Lists environment variables to set when running a task
-                     that is not in the fakeroot environment.
-                     For additional information on environment variables and
-                     the fakeroot environment, see the
-                     <link linkend='var-bb-FAKEROOTENV'><filename>FAKEROOTENV</filename></link>
-                     variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FETCHCMD'><glossterm>FETCHCMD</glossterm>
-            <glossdef>
-                <para>
-                    Defines the command the BitBake fetcher module
-                    executes when running fetch operations.
-                    You need to use an override suffix when you use the
-                    variable (e.g. <filename>FETCHCMD_git</filename>
-                    or <filename>FETCHCMD_svn</filename>).
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FILE'><glossterm>FILE</glossterm>
-            <glossdef>
-                <para>
-                    Points at the current file.
-                    BitBake sets this variable during the parsing process
-                    to identify the file being parsed.
-                    BitBake also sets this variable when a recipe is being
-                    executed to identify the recipe file.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-FILESPATH'><glossterm>FILESPATH</glossterm>
-            <glossdef>
-                <para>
-                    Specifies directories BitBake uses when searching for
-                    patches and files.
-                    The "local" fetcher module uses these directories when
-                    handling <filename>file://</filename> URLs.
-                    The variable behaves like a shell <filename>PATH</filename>
-                    environment variable.
-                    The value is a colon-separated list of directories that
-                    are searched left-to-right in order.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-
-    <glossdiv id='var-bb-glossary-g'><title>G</title>
-
-        <glossentry id='var-bb-GITDIR'><glossterm>GITDIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which a local copy of a Git repository
-                    is stored when it is cloned.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-
-    <glossdiv id='var-bb-glossary-h'><title>H</title>
-
-        <glossentry id='var-bb-HGDIR'><glossterm>HGDIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which files checked out of a Mercurial
-                    system are stored.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-HOMEPAGE'><glossterm>HOMEPAGE</glossterm>
-            <glossdef>
-                <para>Website where more information about the software the recipe is building
-                    can be found.</para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-i'><title>I</title>
-
-        <glossentry id='var-bb-INHERIT'><glossterm>INHERIT</glossterm>
-            <glossdef>
-                <para>
-                    Causes the named class or classes to be inherited globally.
-                    Anonymous functions in the class or classes
-                    are not executed for the
-                    base configuration and in each individual recipe.
-                    The OpenEmbedded build system ignores changes to
-                    <filename>INHERIT</filename> in individual recipes.
-                </para>
-
-                <para>
-                    For more information on <filename>INHERIT</filename>, see
-                    the
-                    "<link linkend="inherit-configuration-directive"><filename>INHERIT</filename> Configuration Directive</link>"
-                    section.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-<!--
-    <glossdiv id='var-glossary-j'><title>J</title>
-    </glossdiv>
-
-    <glossdiv id='var-glossary-k'><title>K</title>
-    </glossdiv>
--->
-
-    <glossdiv id='var-bb-glossary-l'><title>L</title>
-
-        <glossentry id='var-bb-LAYERDEPENDS'><glossterm>LAYERDEPENDS</glossterm>
-            <glossdef>
-                <para>Lists the layers, separated by spaces, upon which this recipe depends.
-                    Optionally, you can specify a specific layer version for a dependency
-                    by adding it to the end of the layer name with a colon, (e.g. "anotherlayer:3"
-                    to be compared against
-                    <link linkend='var-bb-LAYERVERSION'><filename>LAYERVERSION</filename></link><filename>_anotherlayer</filename>
-                    in this case).
-                    BitBake produces an error if any dependency is missing or
-                    the version numbers do not match exactly (if specified).</para>
-                <para>
-                    You use this variable in the <filename>conf/layer.conf</filename> file.
-                    You must also use the specific layer name as a suffix
-                    to the variable (e.g. <filename>LAYERDEPENDS_mylayer</filename>).</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-LAYERDIR'><glossterm>LAYERDIR</glossterm>
-            <glossdef>
-                <para>When used inside the <filename>layer.conf</filename> configuration
-                    file, this variable provides the path of the current layer.
-                    This variable is not available outside of <filename>layer.conf</filename>
-                    and references are expanded immediately when parsing of the file completes.</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-LAYERDIR_RE'><glossterm>LAYERDIR_RE</glossterm>
-            <glossdef>
-                <para>When used inside the <filename>layer.conf</filename> configuration
-                    file, this variable provides the path of the current layer,
-                    escaped for use in a regular expression
-                    (<link linkend='var-bb-BBFILE_PATTERN'><filename>BBFILE_PATTERN</filename></link>).
-                    This variable is not available outside of <filename>layer.conf</filename>
-                    and references are expanded immediately when parsing of the file completes.</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-LAYERVERSION'><glossterm>LAYERVERSION</glossterm>
-            <glossdef>
-                <para>Optionally specifies the version of a layer as a single number.
-                    You can use this variable within
-                    <link linkend='var-bb-LAYERDEPENDS'><filename>LAYERDEPENDS</filename></link>
-                    for another layer in order to depend on a specific version
-                    of the layer.</para>
-                <para>
-                    You use this variable in the <filename>conf/layer.conf</filename> file.
-                    You must also use the specific layer name as a suffix
-                    to the variable (e.g. <filename>LAYERDEPENDS_mylayer</filename>).</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-LICENSE'><glossterm>LICENSE</glossterm>
-            <glossdef>
-                <para>
-                    The list of source licenses for the recipe.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-m'><title>M</title>
-
-        <glossentry id='var-bb-MIRRORS'><glossterm>MIRRORS</glossterm>
-            <glossdef>
-                <para>
-                    Specifies additional paths from which BitBake gets source code.
-                    When the build system searches for source code, it first
-                    tries the local download directory.
-                    If that location fails, the build system tries locations
-                    defined by
-                    <link linkend='var-bb-PREMIRRORS'><filename>PREMIRRORS</filename></link>,
-                    the upstream source, and then locations specified by
-                    <filename>MIRRORS</filename> in that order.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-MULTI_PROVIDER_WHITELIST'><glossterm>MULTI_PROVIDER_WHITELIST</glossterm>
-            <glossdef>
-                <para>
-                    Allows you to suppress BitBake warnings caused when
-                    building two separate recipes that provide the same
-                    output.
-                </para>
-
-                <para>
-                    BitBake normally issues a warning when building two
-                    different recipes where each provides the same output.
-                    This scenario is usually something the user does not
-                    want.
-                    However, cases do exist where it makes sense, particularly
-                    in the <filename>virtual/*</filename> namespace.
-                    You can use this variable to suppress BitBake's warnings.
-                </para>
-
-                <para>
-                    To use the variable, list provider names (e.g.
-                    recipe names, <filename>virtual/kernel</filename>,
-                    and so forth).
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-<!--
-    <glossdiv id='var-glossary-n'><title>N</title>
-    </glossdiv>
--->
-
-    <glossdiv id='var-bb-glossary-o'><title>O</title>
-
-        <glossentry id='var-bb-OVERRIDES'><glossterm>OVERRIDES</glossterm>
-            <glossdef>
-                <para>
-                    BitBake uses <filename>OVERRIDES</filename> to control
-                    what variables are overridden after BitBake parses
-                    recipes and configuration files.
-                </para>
-
-                <para>
-                    Following is a simple example that uses an overrides
-                    list based on machine architectures:
-                    <literallayout class='monospaced'>
-     OVERRIDES = "arm:x86:mips:powerpc"
-                    </literallayout>
-                    You can find information on how to use
-                    <filename>OVERRIDES</filename> in the
-                    "<link linkend='conditional-syntax-overrides'>Conditional Syntax (Overrides)</link>"
-                    section.
-                </para>
-            </glossdef>
-        </glossentry>
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-p'><title>P</title>
-
-        <glossentry id='var-bb-P4DIR'><glossterm>P4DIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which a local copy of a Perforce depot
-                    is stored when it is fetched.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PACKAGES'><glossterm>PACKAGES</glossterm>
-            <glossdef>
-                <para>The list of packages the recipe creates.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PACKAGES_DYNAMIC'><glossterm>PACKAGES_DYNAMIC</glossterm>
-            <glossdef>
-                <para>
-                    A promise that your recipe satisfies runtime dependencies
-                    for optional modules that are found in other recipes.
-                    <filename>PACKAGES_DYNAMIC</filename>
-                    does not actually satisfy the dependencies, it only states that
-                    they should be satisfied.
-                    For example, if a hard, runtime dependency
-                    (<link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link>)
-                    of another package is satisfied during the build
-                    through the <filename>PACKAGES_DYNAMIC</filename>
-                    variable, but a package with the module name is never actually
-                    produced, then the other package will be broken.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PE'><glossterm>PE</glossterm>
-            <glossdef>
-                <para>
-                    The epoch of the recipe.
-                    By default, this variable is unset.
-                    The variable is used to make upgrades possible when the
-                    versioning scheme changes in some backwards incompatible
-                    way.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PERSISTENT_DIR'><glossterm>PERSISTENT_DIR</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the directory BitBake uses to store data that
-                    should be preserved between builds.
-                    In particular, the data stored is the data that uses
-                    BitBake's persistent data API and the data used by the
-                    PR Server and PR Service.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PF'><glossterm>PF</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the recipe or package name and includes all version and revision
-                    numbers (i.e. <filename>eglibc-2.13-r20+svnr15508/</filename> and
-                    <filename>bash-4.2-r1/</filename>).
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PN'><glossterm>PN</glossterm>
-            <glossdef>
-                <para>The recipe name.</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PR'><glossterm>PR</glossterm>
-            <glossdef>
-                <para>The revision of the recipe.
-                    </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PREFERRED_PROVIDER'><glossterm>PREFERRED_PROVIDER</glossterm>
-            <glossdef>
-                <para>
-                    Determines which recipe should be given preference when
-                    multiple recipes provide the same item.
-                    You should always suffix the variable with the name of the
-                    provided item, and you should set it to the
-                    <link linkend='var-bb-PN'><filename>PN</filename></link>
-                    of the recipe to which you want to give precedence.
-                    Some examples:
-                    <literallayout class='monospaced'>
-     PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
-     PREFERRED_PROVIDER_virtual/xserver = "xserver-xf86"
-     PREFERRED_PROVIDER_virtual/libgl ?= "mesa"
-                    </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PREFERRED_PROVIDERS'><glossterm>PREFERRED_PROVIDERS</glossterm>
-            <glossdef>
-                <para>
-                    Determines which recipe should be given preference for
-                    cases where multiple recipes provide the same item.
-                    Functionally,
-                    <filename>PREFERRED_PROVIDERS</filename> is identical to
-                    <link linkend='var-bb-PREFERRED_PROVIDER'><filename>PREFERRED_PROVIDER</filename></link>.
-                    However, the <filename>PREFERRED_PROVIDERS</filename>
-                    variable lets you define preferences for multiple
-                    situations using the following form:
-                    <literallayout class='monospaced'>
-     PREFERRED_PROVIDERS = "xxx:yyy aaa:bbb ..."
-                    </literallayout>
-                    This form is a convenient replacement for the following:
-                    <literallayout class='monospaced'>
-     PREFERRED_PROVIDER_xxx = "yyy"
-     PREFERRED_PROVIDER_aaa = "bbb"
-                    </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PREFERRED_VERSION'><glossterm>PREFERRED_VERSION</glossterm>
-            <glossdef>
-                <para>
-                    If there are multiple versions of recipes available, this
-                    variable determines which recipe should be given preference.
-                    You must always suffix the variable with the
-                    <link linkend='var-bb-PN'><filename>PN</filename></link>
-                    you want to select, and you should set
-                    <link linkend='var-bb-PV'><filename>PV</filename></link>
-                    accordingly for precedence.
-                </para>
-
-                <para>
-                    The <filename>PREFERRED_VERSION</filename> variable
-                    supports limited wildcard use through the
-                    "<filename>%</filename>" character.
-                    You can use the character to match any number of
-                    characters, which can be useful when specifying versions
-                    that contain long revision numbers that potentially change.
-                    Here are two examples:
-                    <literallayout class='monospaced'>
-     PREFERRED_VERSION_python = "2.7.3"
-     PREFERRED_VERSION_linux-yocto = "4.12%"
-                    </literallayout>
-                    <note><title>Important</title>
-                        The use of the "<filename>%</filename>" character
-                        is limited in that it only works at the end of the
-                        string.
-                        You cannot use the wildcard character in any other
-                        location of the string.
-                    </note>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PREMIRRORS'><glossterm>PREMIRRORS</glossterm>
-            <glossdef>
-                <para>
-                    Specifies additional paths from which BitBake gets source code.
-                    When the build system searches for source code, it first
-                    tries the local download directory.
-                    If that location fails, the build system tries locations
-                    defined by <filename>PREMIRRORS</filename>, the upstream
-                    source, and then locations specified by
-                    <link linkend='var-bb-MIRRORS'><filename>MIRRORS</filename></link>
-                    in that order.
-                </para>
-
-                <para>
-                    Typically, you would add a specific server for the
-                    build system to attempt before any others by adding
-                    something like the following to your configuration:
-                    <literallayout class='monospaced'>
-     PREMIRRORS_prepend = "\
-     git://.*/.* http://www.yoctoproject.org/sources/ \n \
-     ftp://.*/.* http://www.yoctoproject.org/sources/ \n \
-     http://.*/.* http://www.yoctoproject.org/sources/ \n \
-     https://.*/.* http://www.yoctoproject.org/sources/ \n"
-                    </literallayout>
-                    These changes cause the build system to intercept
-                    Git, FTP, HTTP, and HTTPS requests and direct them to
-                    the <filename>http://</filename> sources mirror.
-                    You can use <filename>file://</filename> URLs to point
-                    to local directories or network shares as well.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PROVIDES'><glossterm>PROVIDES</glossterm>
-            <glossdef>
-                <para>
-                    A list of aliases by which a particular recipe can be
-                    known.
-                    By default, a recipe's own
-                    <filename><link linkend='var-bb-PN'>PN</link></filename>
-                    is implicitly already in its <filename>PROVIDES</filename>
-                    list.
-                    If a recipe uses <filename>PROVIDES</filename>, the
-                    additional aliases are synonyms for the recipe and can
-                    be useful satisfying dependencies of other recipes during
-                    the build as specified by
-                    <filename><link linkend='var-bb-DEPENDS'>DEPENDS</link></filename>.
-                </para>
-
-                <para>
-                    Consider the following example
-                    <filename>PROVIDES</filename> statement from a recipe
-                    file <filename>libav_0.8.11.bb</filename>:
-                    <literallayout class='monospaced'>
-     PROVIDES += "libpostproc"
-                    </literallayout>
-                    The <filename>PROVIDES</filename> statement results in
-                    the "libav" recipe also being known as "libpostproc".
-                </para>
-
-                <para>
-                    In addition to providing recipes under alternate names,
-                    the <filename>PROVIDES</filename> mechanism is also used
-                    to implement virtual targets.
-                    A virtual target is a name that corresponds to some
-                    particular functionality (e.g. a Linux kernel).
-                    Recipes that provide the functionality in question list the
-                    virtual target in <filename>PROVIDES</filename>.
-                    Recipes that depend on the functionality in question can
-                    include the virtual target in
-                    <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                    to leave the choice of provider open.
-                </para>
-
-                <para>
-                    Conventionally, virtual targets have names on the form
-                    "virtual/function" (e.g. "virtual/kernel").
-                    The slash is simply part of the name and has no
-                    syntactical significance.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PRSERV_HOST'><glossterm>PRSERV_HOST</glossterm>
-            <glossdef>
-                <para>
-                    The network based
-                    <link linkend='var-bb-PR'><filename>PR</filename></link>
-                    service host and port.
-                </para>
-
-                <para>
-                    Following is an example of how the <filename>PRSERV_HOST</filename> variable is
-                    set:
-                    <literallayout class='monospaced'>
-     PRSERV_HOST = "localhost:0"
-                    </literallayout>
-                    You must set the variable if you want to automatically
-                    start a local PR service.
-                    You can set <filename>PRSERV_HOST</filename> to other
-                    values to use a remote PR service.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-PV'><glossterm>PV</glossterm>
-            <glossdef>
-                <para>The version of the recipe.
-                 </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-<!--
-    <glossdiv id='var-glossary-q'><title>Q</title>
-    </glossdiv>
--->
-
-    <glossdiv id='var-bb-glossary-r'><title>R</title>
-
-        <glossentry id='var-bb-RDEPENDS'><glossterm>RDEPENDS</glossterm>
-            <glossdef>
-                <para>
-                    Lists a package's runtime dependencies (i.e. other packages)
-                    that must be installed in order for the built package to run
-                    correctly.
-                    If a package in this list cannot be found during the build,
-                    you will get a build error.
-                </para>
-
-                <para>
-                    Because the <filename>RDEPENDS</filename> variable applies
-                    to packages being built, you should always use the variable
-                    in a form with an attached package name.
-                    For example, suppose you are building a development package
-                    that depends on the <filename>perl</filename> package.
-                    In this case, you would use the following
-                    <filename>RDEPENDS</filename> statement:
-                    <literallayout class='monospaced'>
-     RDEPENDS_${PN}-dev += "perl"
-                    </literallayout>
-                    In the example, the development package depends on
-                    the <filename>perl</filename> package.
-                    Thus, the <filename>RDEPENDS</filename> variable has the
-                    <filename>${PN}-dev</filename> package name as part of the
-                    variable.
-                </para>
-
-                <para>
-                    BitBake supports specifying versioned dependencies.
-                    Although the syntax varies depending on the packaging
-                    format, BitBake hides these differences from you.
-                    Here is the general syntax to specify versions with
-                    the <filename>RDEPENDS</filename> variable:
-                    <literallayout class='monospaced'>
-     RDEPENDS_${PN} = "<replaceable>package</replaceable> (<replaceable>operator</replaceable> <replaceable>version</replaceable>)"
-                    </literallayout>
-                    For <filename>operator</filename>, you can specify the
-                    following:
-                    <literallayout class='monospaced'>
-     =
-     &lt;
-     &gt;
-     &lt;=
-     &gt;=
-                    </literallayout>
-                    For example, the following sets up a dependency on version
-                    1.2 or greater of the package <filename>foo</filename>:
-                    <literallayout class='monospaced'>
-     RDEPENDS_${PN} = "foo (>= 1.2)"
-                    </literallayout>
-                </para>
-
-                <para>
-                    For information on build-time dependencies, see the
-                    <link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link>
-                    variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-REPODIR'><glossterm>REPODIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which a local copy of a
-                    <filename>google-repo</filename> directory is stored
-                    when it is synced.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-RPROVIDES'><glossterm>RPROVIDES</glossterm>
-            <glossdef>
-                <para>
-                    A list of package name aliases that a package also provides.
-                    These aliases are useful for satisfying runtime dependencies
-                    of other packages both during the build and on the target
-                    (as specified by
-                    <filename><link linkend='var-bb-RDEPENDS'>RDEPENDS</link></filename>).
-                </para>
-                <para>
-                   As with all package-controlling variables, you must always
-                   use the variable in conjunction with a package name override.
-                   Here is an example:
-                   <literallayout class='monospaced'>
-     RPROVIDES_${PN} = "widget-abi-2"
-                   </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-RRECOMMENDS'><glossterm>RRECOMMENDS</glossterm>
-            <glossdef>
-                <para>
-                    A list of packages that extends the usability of a package
-                    being built.
-                    The package being built does not depend on this list of
-                    packages in order to successfully build, but needs them for
-                    the extended usability.
-                    To specify runtime dependencies for packages, see the
-                    <filename><link linkend='var-bb-RDEPENDS'>RDEPENDS</link></filename>
-                    variable.
-                </para>
-
-                <para>
-                    BitBake supports specifying versioned recommends.
-                    Although the syntax varies depending on the packaging
-                    format, BitBake hides these differences from you.
-                    Here is the general syntax to specify versions with
-                    the <filename>RRECOMMENDS</filename> variable:
-                    <literallayout class='monospaced'>
-     RRECOMMENDS_${PN} = "<replaceable>package</replaceable> (<replaceable>operator</replaceable> <replaceable>version</replaceable>)"
-                    </literallayout>
-                    For <filename>operator</filename>, you can specify the
-                    following:
-                    <literallayout class='monospaced'>
-     =
-     &lt;
-     &gt;
-     &lt;=
-     &gt;=
-                    </literallayout>
-                    For example, the following sets up a recommend on version
-                    1.2 or greater of the package <filename>foo</filename>:
-                    <literallayout class='monospaced'>
-     RRECOMMENDS_${PN} = "foo (>= 1.2)"
-                    </literallayout>
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-s'><title>S</title>
-
-        <glossentry id='var-bb-SECTION'><glossterm>SECTION</glossterm>
-            <glossdef>
-                <para>The section in which packages should be categorized.</para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SRC_URI'><glossterm>SRC_URI</glossterm>
-            <glossdef>
-                <para>
-                    The list of source files - local or remote.
-                    This variable tells BitBake which bits
-                    to pull for the build and how to pull them.
-                    For example, if the recipe or append file needs to
-                    fetch a single tarball from the Internet, the recipe or
-                    append file uses a <filename>SRC_URI</filename>
-                    entry that specifies that tarball.
-                    On the other hand, if the recipe or append file needs to
-                    fetch a tarball and include a custom file, the recipe or
-                    append file needs an <filename>SRC_URI</filename> variable
-                    that specifies all those sources.</para>
-                <para>The following list explains the available URI protocols:
-                    <itemizedlist>
-                        <listitem><para><emphasis><filename>file://</filename> -</emphasis>
-                            Fetches files, which are usually files shipped with
-                            the metadata,
-                            from the local machine.
-                            The path is relative to the
-                            <link linkend='var-bb-FILESPATH'><filename>FILESPATH</filename></link>
-                            variable.</para></listitem>
-                        <listitem><para><emphasis><filename>bzr://</filename> -</emphasis> Fetches files from a
-                            Bazaar revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>git://</filename> -</emphasis> Fetches files from a
-                            Git revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>osc://</filename> -</emphasis> Fetches files from
-                            an OSC (OpenSUSE Build service) revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>repo://</filename> -</emphasis> Fetches files from
-                            a repo (Git) repository.</para></listitem>
-                        <listitem><para><emphasis><filename>http://</filename> -</emphasis> Fetches files from
-                            the Internet using HTTP.</para></listitem>
-                        <listitem><para><emphasis><filename>https://</filename> -</emphasis> Fetches files
-                            from the Internet using HTTPS.</para></listitem>
-                        <listitem><para><emphasis><filename>ftp://</filename> -</emphasis> Fetches files
-                            from the Internet using FTP.</para></listitem>
-                        <listitem><para><emphasis><filename>cvs://</filename> -</emphasis> Fetches files from
-                            a CVS revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>hg://</filename> -</emphasis> Fetches files from
-                            a Mercurial (<filename>hg</filename>) revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>p4://</filename> -</emphasis> Fetches files from
-                            a Perforce (<filename>p4</filename>) revision control repository.</para></listitem>
-                        <listitem><para><emphasis><filename>ssh://</filename> -</emphasis> Fetches files from
-                            a secure shell.</para></listitem>
-                        <listitem><para><emphasis><filename>svn://</filename> -</emphasis> Fetches files from
-                            a Subversion (<filename>svn</filename>) revision control repository.</para></listitem>
-                    </itemizedlist>
-                </para>
-                <para>Here are some additional options worth mentioning:
-                    <itemizedlist>
-                        <listitem><para><emphasis><filename>unpack</filename> -</emphasis> Controls
-                            whether or not to unpack the file if it is an archive.
-                            The default action is to unpack the file.</para></listitem>
-                        <listitem><para><emphasis><filename>subdir</filename> -</emphasis> Places the file
-                            (or extracts its contents) into the specified
-                            subdirectory.
-                            This option is useful for unusual tarballs or other archives that
-                            do not have their files already in a subdirectory within the archive.
-                            </para></listitem>
-                        <listitem><para><emphasis><filename>name</filename> -</emphasis> Specifies a
-                            name to be used for association with <filename>SRC_URI</filename> checksums
-                            when you have more than one file specified in <filename>SRC_URI</filename>.
-                            </para></listitem>
-                        <listitem><para><emphasis><filename>downloadfilename</filename> -</emphasis> Specifies
-                            the filename used when storing the downloaded file.</para></listitem>
-                    </itemizedlist>
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SRCDATE'><glossterm>SRCDATE</glossterm>
-            <glossdef>
-                <para>
-                    The date of the source code used to build the package.
-                    This variable applies only if the source was fetched from a Source Code Manager (SCM).
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SRCREV'><glossterm>SRCREV</glossterm>
-            <glossdef>
-                <para>
-                    The revision of the source code used to build the package.
-                    This variable applies only when using Subversion, Git, Mercurial and Bazaar.
-                    If you want to build a fixed revision and you want
-                    to avoid performing a query on the remote repository every time
-                    BitBake parses your recipe, you should specify a <filename>SRCREV</filename> that is a
-                    full revision identifier and not just a tag.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SRCREV_FORMAT'><glossterm>SRCREV_FORMAT</glossterm>
-            <glossdef>
-                <para>
-                    Helps construct valid
-                    <link linkend='var-bb-SRCREV'><filename>SRCREV</filename></link>
-                    values when multiple source controlled URLs are used in
-                    <link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>.
-                </para>
-
-                <para>
-                    The system needs help constructing these values under these
-                    circumstances.
-                    Each component in the <filename>SRC_URI</filename>
-                    is assigned a name and these are referenced
-                    in the <filename>SRCREV_FORMAT</filename> variable.
-                    Consider an example with URLs named "machine" and "meta".
-                    In this case, <filename>SRCREV_FORMAT</filename> could look
-                    like "machine_meta" and those names would have the SCM
-                    versions substituted into each position.
-                    Only one <filename>AUTOINC</filename> placeholder is added
-                    and if needed.
-                    And, this placeholder is placed at the start of the
-                    returned string.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-STAMP'><glossterm>STAMP</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the base path used to create recipe stamp files.
-                    The path to an actual stamp file is constructed by evaluating this
-                    string and then appending additional information.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-STAMPCLEAN'><glossterm>STAMPCLEAN</glossterm>
-            <glossdef>
-                <para>
-                    Specifies the base path used to create recipe stamp files.
-                    Unlike the
-                    <link linkend='var-bb-STAMP'><filename>STAMP</filename></link>
-                    variable, <filename>STAMPCLEAN</filename> can contain
-                    wildcards to match the range of files a clean operation
-                    should remove.
-                    BitBake uses a clean operation to remove any other stamps
-                    it should be removing when creating a new stamp.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SUMMARY'><glossterm>SUMMARY</glossterm>
-            <glossdef>
-                <para>
-                    A short summary for the recipe, which is 72 characters or less.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-SVNDIR'><glossterm>SVNDIR</glossterm>
-            <glossdef>
-                <para>
-                    The directory in which files checked out of a Subversion
-                    system are stored.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-    <glossdiv id='var-bb-glossary-t'><title>T</title>
-
-        <glossentry id='var-bb-T'><glossterm>T</glossterm>
-            <glossdef>
-                <para>Points to a directory were BitBake places
-                    temporary files, which consist mostly of task logs and
-                    scripts, when building a particular recipe.
-                </para>
-            </glossdef>
-        </glossentry>
-
-        <glossentry id='var-bb-TOPDIR'><glossterm>TOPDIR</glossterm>
-            <glossdef>
-                <para>
-                    Points to the build directory.
-                    BitBake automatically sets this variable.
-                </para>
-            </glossdef>
-        </glossentry>
-
-    </glossdiv>
-
-<!--
-    <glossdiv id='var-glossary-u'><title>U</title>
-    </glossdiv>
-
-    <glossdiv id='var-glossary-v'><title>V</title>
-   </glossdiv>
-
-    <glossdiv id='var-glossary-w'><title>W</title>
-    </glossdiv>
-
-    <glossdiv id='var-glossary-x'><title>X</title>
-    </glossdiv>
-
-    <glossdiv id='var-glossary-y'><title>Y</title>
-    </glossdiv>
-
-    <glossdiv id='var-glossary-z'><title>Z</title>
-    </glossdiv>
--->
-
-
-</glossary>
-</chapter>
-<!--
-vim: expandtab tw=80 ts=4
--->
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css b/bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
deleted file mode 100644
index 65da2a4e..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
-   Generic XHTML / DocBook XHTML CSS Stylesheet.
-
-   Browser wrangling and typographic design by
-      Oyvind Kolas / pippin@gimp.org
-
-   Customised for Poky by
-      Matthew Allum / mallum@o-hand.com
-
-   Thanks to:
-     Liam R. E. Quin
-     William Skaggs
-     Jakub Steiner
-
-   Structure
-   ---------
-
-   The stylesheet is divided into the following sections:
-
-       Positioning
-          Margins, paddings, width, font-size, clearing.
-       Decorations
-          Borders, style
-       Colors
-          Colors
-       Graphics
-          Graphical backgrounds
-       Nasty IE tweaks
-          Workarounds needed to make it work in internet explorer,
-          currently makes the stylesheet non validating, but up until
-          this point it is validating.
-       Mozilla extensions
-          Transparency for footer
-	  Rounded corners on boxes
-
-*/
-
-
-  /*************** /
- /  Positioning   /
-/ ***************/
-
-body {
-  font-family: Verdana, Sans, sans-serif;
-
-  min-width: 640px;
-  width: 80%;
-  margin:  0em auto;
-  padding: 2em 5em 5em 5em;
-  color: #333;
-}
-
-h1,h2,h3,h4,h5,h6,h7 {
-  font-family: Arial, Sans;
-  color: #00557D;
-  clear: both;
-}
-
-h1 {
-  font-size: 2em;
-  text-align: left;
-  padding: 0em 0em 0em 0em;
-  margin: 2em 0em 0em 0em;
-}
-
-h2.subtitle {
-  margin: 0.10em 0em 3.0em 0em;
-  padding: 0em 0em 0em 0em;
-  font-size: 1.8em;
-  padding-left: 20%;
-  font-weight: normal;
-  font-style: italic;
-}
-
-h2 {
-  margin: 2em 0em 0.66em 0em;
-  padding: 0.5em 0em 0em 0em;
-  font-size: 1.5em;
-  font-weight: bold;
-}
-
-h3.subtitle {
-  margin: 0em 0em 1em 0em;
-  padding: 0em 0em 0em 0em;
-  font-size: 142.14%;
-  text-align: right;
-}
-
-h3 {
-  margin: 1em 0em 0.5em 0em;
-  padding: 1em 0em 0em 0em;
-  font-size: 140%;
-  font-weight: bold;
-}
-
-h4 {
-  margin: 1em 0em 0.5em 0em;
-  padding: 1em 0em 0em 0em;
-  font-size: 120%;
-  font-weight: bold;
-}
-
-h5 {
-  margin: 1em 0em 0.5em 0em;
-  padding: 1em 0em 0em 0em;
-  font-size: 110%;
-  font-weight: bold;
-}
-
-h6 {
-  margin: 1em 0em 0em 0em;
-  padding: 1em 0em 0em 0em;
-  font-size: 110%;
-  font-weight: bold;
-}
-
-.authorgroup {
-  background-color: transparent;
-  background-repeat: no-repeat;
-  padding-top: 256px;
-  background-image: url("figures/bitbake-title.png");
-  background-position: left top;
-  margin-top: -256px;
-  padding-right: 50px;
-  margin-left: 0px;
-  text-align: right;
-  width: 740px;
-}
-
-h3.author {
-  margin: 0em 0me 0em 0em;
-  padding: 0em 0em 0em 0em;
-  font-weight: normal;
-  font-size: 100%;
-  color: #333;
-  clear: both;
-}
-
-.author tt.email {
-  font-size: 66%;
-}
-
-.titlepage hr {
-  width: 0em;
-  clear: both;
-}
-
-.revhistory {
-  padding-top: 2em;
-  clear: both;
-}
-
-.toc,
-.list-of-tables,
-.list-of-examples,
-.list-of-figures {
-  padding: 1.33em 0em 2.5em 0em;
-  color: #00557D;
-}
-
-.toc p,
-.list-of-tables p,
-.list-of-figures p,
-.list-of-examples p {
-  padding: 0em 0em 0em 0em;
-  padding: 0em 0em 0.3em;
-  margin: 1.5em 0em 0em 0em;
-}
-
-.toc p b,
-.list-of-tables p b,
-.list-of-figures p b,
-.list-of-examples p b{
-  font-size: 100.0%;
-  font-weight: bold;
-}
-
-.toc dl,
-.list-of-tables dl,
-.list-of-figures dl,
-.list-of-examples dl {
-  margin: 0em 0em 0.5em 0em;
-  padding: 0em 0em 0em 0em;
-}
-
-.toc dt {
-  margin: 0em 0em 0em 0em;
-  padding: 0em 0em 0em 0em;
-}
-
-.toc dd {
-  margin: 0em 0em 0em 2.6em;
-  padding: 0em 0em 0em 0em;
-}
-
-div.glossary dl,
-div.variablelist dl {
-}
-
-.glossary dl dt,
-.variablelist dl dt,
-.variablelist dl dt span.term {
-  font-weight: normal;
-  width: 20em;
-  text-align: right;
-}
-
-.variablelist dl dt {
-  margin-top: 0.5em;
-}
-
-.glossary dl dd,
-.variablelist dl dd {
-  margin-top: -1em;
-  margin-left: 25.5em;
-}
-
-.glossary dd p,
-.variablelist dd p {
-  margin-top: 0em;
-  margin-bottom: 1em;
-}
-
-
-div.calloutlist table td {
-  padding: 0em 0em 0em 0em;
-  margin: 0em 0em 0em 0em;
-}
-
-div.calloutlist table td p {
-  margin-top: 0em;
-  margin-bottom: 1em;
-}
-
-div p.copyright {
-  text-align: left;
-}
-
-div.legalnotice p.legalnotice-title {
-  margin-bottom: 0em;
-}
-
-p {
-  line-height: 1.5em;
-  margin-top: 0em;
-
-}
-
-dl {
-  padding-top: 0em;
-}
-
-hr {
-  border: solid 1px;
-}
-
-
-.mediaobject,
-.mediaobjectco {
-  text-align: center;
-}
-
-img {
-  border: none;
-}
-
-ul {
-  padding: 0em 0em 0em 1.5em;
-}
-
-ul li {
-  padding: 0em 0em 0em 0em;
-}
-
-ul li p {
-  text-align: left;
-}
-
-table {
-  width :100%;
-}
-
-th {
-  padding: 0.25em;
-  text-align: left;
-  font-weight: normal;
-  vertical-align: top;
-}
-
-td {
-  padding: 0.25em;
-  vertical-align: top;
-}
-
-p a[id] {
-  margin: 0px;
-  padding: 0px;
-  display: inline;
-  background-image: none;
-}
-
-a {
-  text-decoration: underline;
-  color: #444;
-}
-
-pre {
-    overflow: auto;
-}
-
-a:hover {
-  text-decoration: underline;
-  /*font-weight: bold;*/
-}
-
-/* This style defines how the permalink character
-   appears by itself and when hovered over with
-   the mouse. */
-
-[alt='Permalink'] { color: #eee; }
-[alt='Permalink']:hover { color: black; }
-
-
-div.informalfigure,
-div.informalexample,
-div.informaltable,
-div.figure,
-div.table,
-div.example {
-  margin: 1em 0em;
-  padding: 1em;
-  page-break-inside: avoid;
-}
-
-
-div.informalfigure p.title b,
-div.informalexample p.title b,
-div.informaltable p.title b,
-div.figure p.title b,
-div.example p.title b,
-div.table p.title b{
-    padding-top: 0em;
-    margin-top: 0em;
-    font-size: 100%;
-    font-weight: normal;
-}
-
-.mediaobject .caption,
-.mediaobject .caption p  {
-  text-align: center;
-  font-size: 80%;
-  padding-top: 0.5em;
-  padding-bottom: 0.5em;
-}
-
-.epigraph {
-  padding-left: 55%;
-  margin-bottom: 1em;
-}
-
-.epigraph p {
-  text-align: left;
-}
-
-.epigraph .quote {
-  font-style: italic;
-}
-.epigraph .attribution {
-  font-style: normal;
-  text-align: right;
-}
-
-span.application {
-  font-style: italic;
-}
-
-.programlisting {
-  font-family: monospace;
-  font-size: 80%;
-  white-space: pre;
-  margin: 1.33em 0em;
-  padding: 1.33em;
-}
-
-.tip,
-.warning,
-.caution,
-.note {
-  margin-top: 1em;
-  margin-bottom: 1em;
-
-}
-
-/* force full width of table within div */
-.tip table,
-.warning table,
-.caution table,
-.note table {
-  border: none;
-  width: 100%;
-}
-
-
-.tip table th,
-.warning table th,
-.caution table th,
-.note table th {
-  padding: 0.8em 0.0em 0.0em 0.0em;
-  margin : 0em 0em 0em 0em;
-}
-
-.tip p,
-.warning p,
-.caution p,
-.note p {
-  margin-top: 0.5em;
-  margin-bottom: 0.5em;
-  padding-right: 1em;
-  text-align: left;
-}
-
-.acronym {
-  text-transform: uppercase;
-}
-
-b.keycap,
-.keycap {
-  padding: 0.09em 0.3em;
-  margin: 0em;
-}
-
-.itemizedlist li {
-  clear: none;
-}
-
-.filename {
-  font-size: medium;
-  font-family: Courier, monospace;
-}
-
-
-div.navheader, div.heading{
-  position: absolute;
-  left: 0em;
-  top: 0em;
-  width: 100%;
-  background-color: #cdf;
-  width: 100%;
-}
-
-div.navfooter, div.footing{
-  position: fixed;
-  left: 0em;
-  bottom: 0em;
-  background-color: #eee;
-  width: 100%;
-}
-
-
-div.navheader td,
-div.navfooter td {
-  font-size: 66%;
-}
-
-div.navheader table th {
-  /*font-family: Georgia, Times, serif;*/
-  /*font-size: x-large;*/
-  font-size: 80%;
-}
-
-div.navheader table {
-  border-left: 0em;
-  border-right: 0em;
-  border-top: 0em;
-  width: 100%;
-}
-
-div.navfooter table {
-  border-left: 0em;
-  border-right: 0em;
-  border-bottom: 0em;
-  width: 100%;
-}
-
-div.navheader table td a,
-div.navfooter table td a {
-  color: #777;
-  text-decoration: none;
-}
-
-/* normal text in the footer */
-div.navfooter table td {
-  color: black;
-}
-
-div.navheader table td a:visited,
-div.navfooter table td a:visited {
-  color: #444;
-}
-
-
-/* links in header and footer */
-div.navheader table td a:hover,
-div.navfooter table td a:hover {
-  text-decoration: underline;
-  background-color: transparent;
-  color: #33a;
-}
-
-div.navheader hr,
-div.navfooter hr {
-  display: none;
-}
-
-
-.qandaset tr.question td p {
-  margin: 0em 0em 1em 0em;
-  padding: 0em 0em 0em 0em;
-}
-
-.qandaset tr.answer td p {
-  margin: 0em 0em 1em 0em;
-  padding: 0em 0em 0em 0em;
-}
-.answer td {
-  padding-bottom: 1.5em;
-}
-
-.emphasis {
-  font-weight: bold;
-}
-
-
-  /************* /
- / decorations  /
-/ *************/
-
-.titlepage {
-}
-
-.part .title {
-}
-
-.subtitle {
-    border: none;
-}
-
-/*
-h1 {
-  border: none;
-}
-
-h2 {
-  border-top: solid 0.2em;
-  border-bottom: solid 0.06em;
-}
-
-h3 {
-  border-top: 0em;
-  border-bottom: solid 0.06em;
-}
-
-h4 {
-  border: 0em;
-  border-bottom: solid 0.06em;
-}
-
-h5 {
-  border: 0em;
-}
-*/
-
-.programlisting {
-  border: solid 1px;
-}
-
-div.figure,
-div.table,
-div.informalfigure,
-div.informaltable,
-div.informalexample,
-div.example {
-  border: 1px solid;
-}
-
-
-
-.tip,
-.warning,
-.caution,
-.note {
-  border: 1px solid;
-}
-
-.tip table th,
-.warning table th,
-.caution table th,
-.note table th {
-  border-bottom: 1px solid;
-}
-
-.question td {
-  border-top: 1px solid black;
-}
-
-.answer {
-}
-
-
-b.keycap,
-.keycap {
-  border: 1px solid;
-}
-
-
-div.navheader, div.heading{
-  border-bottom: 1px solid;
-}
-
-
-div.navfooter, div.footing{
-  border-top: 1px solid;
-}
-
-  /********* /
- /  colors  /
-/ *********/
-
-body {
-  color: #333;
-  background: white;
-}
-
-a {
-  background: transparent;
-}
-
-a:hover {
-  background-color: #dedede;
-}
-
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-h7,
-h8 {
-  background-color: transparent;
-}
-
-hr {
-  border-color: #aaa;
-}
-
-
-.tip, .warning, .caution, .note {
-  border-color: #fff;
-}
-
-
-.tip table th,
-.warning table th,
-.caution table th,
-.note table th {
-  border-bottom-color: #fff;
-}
-
-
-.warning {
-  background-color: #f0f0f2;
-}
-
-.caution {
-  background-color: #f0f0f2;
-}
-
-.tip {
-  background-color: #f0f0f2;
-}
-
-.note {
-  background-color: #f0f0f2;
-}
-
-.glossary dl dt,
-.variablelist dl dt,
-.variablelist dl dt span.term {
-  color: #044;
-}
-
-div.figure,
-div.table,
-div.example,
-div.informalfigure,
-div.informaltable,
-div.informalexample {
-  border-color: #aaa;
-}
-
-pre.programlisting {
-  color: black;
-  background-color: #fff;
-  border-color: #aaa;
-  border-width: 2px;
-}
-
-.guimenu,
-.guilabel,
-.guimenuitem {
-  background-color: #eee;
-}
-
-
-b.keycap,
-.keycap {
-  background-color: #eee;
-  border-color: #999;
-}
-
-
-div.navheader {
-  border-color: black;
-}
-
-
-div.navfooter {
-  border-color: black;
-}
-
-
-  /*********** /
- /  graphics  /
-/ ***********/
-
-/*
-body {
-  background-image: url("images/body_bg.jpg");
-  background-attachment: fixed;
-}
-
-.navheader,
-.note,
-.tip {
-  background-image: url("images/note_bg.jpg");
-  background-attachment: fixed;
-}
-
-.warning,
-.caution {
-  background-image: url("images/warning_bg.jpg");
-  background-attachment: fixed;
-}
-
-.figure,
-.informalfigure,
-.example,
-.informalexample,
-.table,
-.informaltable {
-  background-image: url("images/figure_bg.jpg");
-  background-attachment: fixed;
-}
-
-*/
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-h7{
-}
-
-/*
-Example of how to stick an image as part of the title.
-
-div.article .titlepage .title
-{
-  background-image: url("figures/white-on-black.png");
-  background-position: center;
-  background-repeat: repeat-x;
-}
-*/
-
-div.preface .titlepage .title,
-div.colophon .title,
-div.chapter .titlepage .title,
-div.article .titlepage .title
-{
-}
-
-div.section div.section .titlepage .title,
-div.sect2 .titlepage .title {
-    background: none;
-}
-
-
-h1.title {
-  background-color: transparent;
-  background-repeat: no-repeat;
-  height: 256px;
-  text-indent: -9000px;
-  overflow:hidden;
-}
-
-h2.subtitle {
-  background-color: transparent;
-  text-indent: -9000px;
-  overflow:hidden;
-  width: 0px;
-  display: none;
-}
-
-  /*************************************** /
- /  pippin.gimp.org specific alterations  /
-/ ***************************************/
-
-/*
-div.heading, div.navheader {
-  color: #777;
-  font-size: 80%;
-  padding: 0;
-  margin: 0;
-  text-align: left;
-  position: absolute;
-  top: 0px;
-  left: 0px;
-  width: 100%;
-  height: 50px;
-  background: url('/gfx/heading_bg.png') transparent;
-  background-repeat: repeat-x;
-  background-attachment: fixed;
-  border: none;
-}
-
-div.heading a {
-  color: #444;
-}
-
-div.footing, div.navfooter {
-  border: none;
-  color: #ddd;
-  font-size: 80%;
-  text-align:right;
-
-  width: 100%;
-  padding-top: 10px;
-  position: absolute;
-  bottom: 0px;
-  left: 0px;
-
-  background: url('/gfx/footing_bg.png') transparent;
-}
-*/
-
-
-
-  /****************** /
- /  nasty ie tweaks  /
-/ ******************/
-
-/*
-div.heading, div.navheader {
-  width:expression(document.body.clientWidth + "px");
-}
-
-div.footing, div.navfooter {
-  width:expression(document.body.clientWidth + "px");
-  margin-left:expression("-5em");
-}
-body {
-  padding:expression("4em 5em 0em 5em");
-}
-*/
-
-  /**************************************** /
- / mozilla vendor specific css extensions  /
-/ ****************************************/
-/*
-div.navfooter, div.footing{
-  -moz-opacity: 0.8em;
-}
-
-div.figure,
-div.table,
-div.informalfigure,
-div.informaltable,
-div.informalexample,
-div.example,
-.tip,
-.warning,
-.caution,
-.note {
-  -moz-border-radius: 0.5em;
-}
-
-b.keycap,
-.keycap {
-  -moz-border-radius: 0.3em;
-}
-*/
-
-table tr td table tr td {
-  display: none;
-}
-
-
-hr {
-  display: none;
-}
-
-table {
-  border: 0em;
-}
-
- .photo {
-  float: right;
-  margin-left:   1.5em;
-  margin-bottom: 1.5em;
-  margin-top: 0em;
-  max-width:      17em;
-  border:     1px solid gray;
-  padding:    3px;
-  background: white;
-}
- .seperator {
-   padding-top: 2em;
-   clear: both;
-  }
-
-  #validators {
-      margin-top: 5em;
-      text-align: right;
-      color: #777;
-  }
-  @media print {
-      body {
-          font-size: 8pt;
-      }
-      .noprint {
-          display: none;
-      }
-  }
-
-
-.tip,
-.note {
-   background: #f0f0f2;
-   color: #333;
-   padding: 20px;
-   margin: 20px;
-}
-
-.tip h3,
-.note h3 {
-   padding: 0em;
-   margin: 0em;
-   font-size: 2em;
-   font-weight: bold;
-   color: #333;
-}
-
-.tip a,
-.note a {
-   color: #333;
-   text-decoration: underline;
-}
-
-.footnote {
-   font-size: small;
-   color: #333;
-}
-
-/* Changes the announcement text */
-.tip h3,
-.warning h3,
-.caution h3,
-.note h3 {
-   font-size:large;
-   color: #00557D;
-}
diff --git a/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml b/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
deleted file mode 100644
index d793265c..00000000
--- a/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
-"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<book id='bitbake-user-manual' lang='en'
-        xmlns:xi="http://www.w3.org/2003/XInclude"
-        xmlns="http://docbook.org/ns/docbook"
-        >
-    <bookinfo>
-
-        <mediaobject>
-            <imageobject>
-                <imagedata fileref='figures/bitbake-title.png'
-                    format='SVG'
-                    align='left' scalefit='1' width='100%'/>
-            </imageobject>
-        </mediaobject>
-
-        <title>
-            BitBake User Manual
-        </title>
-
-        <authorgroup>
-            <author>
-                <firstname>Richard Purdie, Chris Larson, and </firstname> <surname>Phil Blundell</surname>
-                <affiliation>
-                    <orgname>BitBake Community</orgname>
-                </affiliation>
-                <email>bitbake-devel@lists.openembedded.org</email>
-            </author>
-        </authorgroup>
-
-<!--
-# Add in some revision history if we want it here.
-        <revhistory>
-            <revision>
-                <revnumber>x.x</revnumber>
-                <date>dd month year</date>
-                <revremark>Some relevent comment</revremark>
-            </revision>
-            <revision>
-                <revnumber>x.x</revnumber>
-                <date>dd month year</date>
-                <revremark>Some relevent comment</revremark>
-            </revision>
-            <revision>
-                <revnumber>x.x</revnumber>
-                <date>dd month year</date>
-                <revremark>Some relevent comment</revremark>
-            </revision>
-            <revision>
-                <revnumber>x.x</revnumber>
-                <date>dd month year</date>
-                <revremark>Some relevent comment</revremark>
-            </revision>
-       </revhistory>
--->
-
-        <copyright>
-            <year>2004-2018</year>
-            <holder>Richard Purdie</holder>
-            <holder>Chris Larson</holder>
-            <holder>and Phil Blundell</holder>
-        </copyright>
-
-        <legalnotice>
-            <para>
-                This work is licensed under the Creative Commons Attribution License.
-                To view a copy of this license, visit
-                <ulink url="http://creativecommons.org/licenses/by/2.5/">http://creativecommons.org/licenses/by/2.5/</ulink>
-                or send a letter to Creative Commons, 444 Castro Street,
-                Suite 900, Mountain View, California 94041, USA.
-            </para>
-        </legalnotice>
-    </bookinfo>
-
-    <xi:include href="bitbake-user-manual-intro.xml"/>
-
-    <xi:include href="bitbake-user-manual-execution.xml"/>
-
-    <xi:include href="bitbake-user-manual-metadata.xml"/>
-
-    <xi:include href="bitbake-user-manual-fetching.xml"/>
-
-    <xi:include href="bitbake-user-manual-ref-variables.xml"/>
-
-    <xi:include href="bitbake-user-manual-hello.xml"/>
-
-</book>
diff --git a/bitbake/doc/bitbake-user-manual/html.css b/bitbake/doc/bitbake-user-manual/html.css
deleted file mode 100644
index 6eedfd31..00000000
--- a/bitbake/doc/bitbake-user-manual/html.css
+++ /dev/null
@@ -1,281 +0,0 @@
-/* Feuille de style DocBook du projet Traduc.org                */
-/* DocBook CSS stylesheet of the Traduc.org project             */
-
-/* (c) Jean-Philippe Guérard - 14 août 2004                     */
-/* (c) Jean-Philippe Guérard - 14 August 2004                   */
-
-/* Cette feuille de style est libre, vous pouvez la             */
-/* redistribuer et la modifier selon les termes de la Licence   */
-/* Art Libre. Vous trouverez un exemplaire de cette Licence sur */
-/* http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
-
-/* This work of art is free, you can redistribute it and/or     */
-/* modify it according to terms of the Free Art license. You    */
-/* will find a specimen of this license on the Copyleft         */
-/* Attitude web site: http://artlibre.org as well as on other   */
-/* sites.                                                       */
-/* Please note that the French version of this licence as shown */
-/* on http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
-/* is only official licence of this document. The English       */
-/* is only provided to help you understand this licence.        */
-
-/* La dernière version de cette feuille de style est toujours   */
-/* disponible sur : http://tigreraye.org/style.css              */
-/* Elle est également disponible sur :                          */
-/* http://www.traduc.org/docs/HOWTO/lecture/style.css           */
-
-/* The latest version of this stylesheet is available from:     */
-/* http://tigreraye.org/style.css                               */
-/* It is also available on:                                     */
-/* http://www.traduc.org/docs/HOWTO/lecture/style.css           */
-
-/* N'hésitez pas à envoyer vos commentaires et corrections à    */
-/* Jean-Philippe Guérard <jean-philippe.guerard@tigreraye.org>  */
-
-/* Please send feedback and bug reports to                      */
-/* Jean-Philippe Guérard <jean-philippe.guerard@tigreraye.org>  */
-
-/* $Id: style.css,v 1.14 2004/09/10 20:12:09 fevrier Exp fevrier $ */
-
-/* Présentation générale du document */
-/* Overall document presentation */
-
-body {
-    /*
-    font-family: Apolline, "URW Palladio L", Garamond, jGaramond,
-                 "Bitstream Cyberbit", "Palatino Linotype", serif;
-     */
-    margin: 7%;
-    background-color: white;
-}
-
-/* Taille du texte */
-/* Text size */
-
-* { font-size: 100%; }
-
-/* Gestion des textes mis en relief imbriqués */
-/* Embedded emphasis */
-
-em { font-style: italic; }
-em em { font-style: normal; }
-em em em { font-style: italic; }
-
-/* Titres */
-/* Titles */
-
-h1 { font-size: 200%; font-weight: 900; }
-h2 { font-size: 160%; font-weight: 900; }
-h3 { font-size: 130%; font-weight: bold; }
-h4 { font-size: 115%; font-weight: bold; }
-h5 { font-size: 108%; font-weight: bold; }
-h6 {                  font-weight: bold; }
-
-/* Nom de famille en petites majuscules (uniquement en français) */
-/* Last names in small caps (for French only) */
-
-*[class~="surname"]:lang(fr) { font-variant: small-caps; }
-
-/* Blocs de citation */
-/* Quotation blocs */
-
-div[class~="blockquote"] {
-  border: solid 2px #AAA;
-  padding: 5px;
-  margin: 5px;
-}
-
-div[class~="blockquote"] > table {
-  border: none;
-}
-
-/* Blocs litéraux : fond gris clair */
-/* Literal blocs: light gray background */
-
-*[class~="literallayout"] {
-  background: #f0f0f0;
-  padding: 5px;
-  margin: 5px;
-}
-
-/* Programmes et captures texte : fond bleu clair */
-/* Listing and text screen snapshots: light blue background */
-
-*[class~="programlisting"], *[class~="screen"] {
-  background: #f0f0ff;
-  padding: 5px;
-  margin: 5px;
-}
-
-/* Les textes à remplacer sont surlignés en vert pâle */
-/* Replaceable text in highlighted in pale green */
-
-*[class~="replaceable"] { 
-    background-color: #98fb98;
-    font-style: normal; }
-
-/* Tables : fonds gris clair & bords simples */
-/* Tables: light gray background and solid borders */
-
-*[class~="table"] *[class~="title"] { width:100%; border: 0px; }
-
-table {
-    border: 1px solid #aaa;
-    border-collapse: collapse;
-    padding: 2px;
-    margin: 5px;
-}
-
-/* Listes simples en style table */
-/* Simples lists in table presentation */
-
-table[class~="simplelist"] {
-    background-color: #F0F0F0;
-    margin: 5px;
-    border: solid 1px #AAA;
-}
-
-table[class~="simplelist"] td {
-    border: solid 1px #AAA;
-}
-
-/* Les tables */
-/* Tables */
-
-*[class~="table"] table {
-    background-color: #F0F0F0;
-    border: solid 1px #AAA;
-}
-*[class~="informaltable"] table { background-color: #F0F0F0; }
-
-th,td {
-    vertical-align: baseline;
-    text-align: left;
-    padding: 0.1em 0.3em;
-    empty-cells: show; 
-}
-
-/* Alignement des colonnes */
-/* Colunms alignment */
-
-td[align=center] ,  th[align=center]  { text-align: center; }
-td[align=right] ,   th[align=right]   { text-align: right; }
-td[align=left] ,    th[align=left]    { text-align: left; }
-td[align=justify] , th[align=justify] { text-align: justify; }
-
-/* Pas de marge autour des images */
-/* No inside margins for images */
-
-img { border: 0; }
-
-/* Les liens ne sont pas soulignés */
-/* No underlines for links */
-
-:link , :visited , :active { text-decoration: none; }
-
-/* Prudence : cadre jaune et fond jaune clair */
-/* Caution: yellow border and light yellow background */
-
-*[class~="caution"] {
-    border: solid 2px yellow;
-    background-color: #ffffe0;
-    padding: 1em 6px 1em ;
-    margin: 5px;
-}
-
-*[class~="caution"] th {
-    vertical-align: middle
-}
-
-*[class~="caution"] table {
-    background-color: #ffffe0;
-    border: none;
-}
-
-/* Note importante : cadre jaune et fond jaune clair */
-/* Important: yellow border and light yellow background */
-
-*[class~="important"] {
-    border: solid 2px yellow;
-    background-color: #ffffe0;
-    padding: 1em 6px 1em;
-    margin: 5px;
-}
-
-*[class~="important"] th {
-    vertical-align: middle
-}
-
-*[class~="important"] table  {
-    background-color: #ffffe0;
-    border: none;
-}
-
-/* Mise en évidence : texte légèrement plus grand */
-/* Highlights: slightly larger texts */
-
-*[class~="highlights"] {
-    font-size:  110%;
-}
-
-/* Note : cadre bleu et fond bleu clair */
-/* Notes: blue border and light blue background */
-
-*[class~="note"]   {
-    border: solid 2px #7099C5;
-    background-color: #f0f0ff;
-    padding: 1em 6px 1em ;
-    margin: 5px;
-}
-
-*[class~="note"] th {
-    vertical-align: middle
-}
-
-*[class~="note"] table {
-    background-color: #f0f0ff;
-    border: none;
-}
-
-/* Astuce : cadre vert et fond vert clair */
-/* Tip: green border and light green background */
-
-*[class~="tip"] {
-    border: solid 2px #00ff00;
-    background-color: #f0ffff;
-    padding: 1em 6px 1em ;
-    margin: 5px;
-}
-
-*[class~="tip"] th {
-    vertical-align: middle;
-}
-
-*[class~="tip"] table {
-    background-color: #f0ffff;
-    border: none;
-}
-
-/* Avertissement : cadre rouge et fond rouge clair */
-/* Warning: red border and light red background */
-
-*[class~="warning"] {
-    border: solid 2px #ff0000;
-    background-color: #fff0f0; 
-    padding: 1em 6px 1em ;
-    margin: 5px;
-}
-
-*[class~="warning"] th {
-    vertical-align: middle;
-}
-                    
-
-*[class~="warning"] table {
-    background-color: #fff0f0;
-    border: none;
-}
-
-/* Fin */
-/* The End */
-
diff --git a/bitbake/doc/conf.py b/bitbake/doc/conf.py
new file mode 100644
index 00000000..fc2ee081
--- /dev/null
+++ b/bitbake/doc/conf.py
@@ -0,0 +1,101 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# This file only contains a selection of the most common options. For a full
+# list see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+import sys
+import datetime
+
+current_version = "dev"
+
+# String used in sidebar
+version = 'Version: ' + current_version
+if current_version == 'dev':
+    version = 'Version: Current Development'
+# Version seen in documentation_options.js and hence in js switchers code
+release = current_version
+
+# -- Project information -----------------------------------------------------
+
+project = 'Bitbake'
+copyright = '2004-%s, Richard Purdie, Chris Larson, and Phil Blundell' \
+    % datetime.datetime.now().year
+author = 'Richard Purdie, Chris Larson, and Phil Blundell'
+
+# external links and substitutions
+extlinks = {
+    'yocto_docs': ('https://docs.yoctoproject.org%s', None),
+    'oe_lists': ('https://lists.openembedded.org%s', None),
+}
+
+# -- General configuration ---------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.autosectionlabel',
+    'sphinx.ext.extlinks',
+]
+autosectionlabel_prefix_document = True
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+# master document name. The default changed from contents to index. so better
+# set it ourselves.
+master_doc = 'index'
+
+# create substitution for project configuration variables
+rst_prolog = """
+.. |project_name| replace:: %s
+.. |copyright| replace:: %s
+.. |author| replace:: %s
+""" % (project, copyright, author)
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+try:
+    import sphinx_rtd_theme
+    html_theme = 'sphinx_rtd_theme'
+except ImportError:
+    sys.stderr.write("The Sphinx sphinx_rtd_theme HTML theme was not found.\
+    \nPlease make sure to install the sphinx_rtd_theme python package.\n")
+    sys.exit(1)
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['sphinx-static']
+
+# Add customm CSS and JS files
+html_css_files = ['theme_overrides.css']
+html_js_files = ['switchers.js']
+
+# Hide 'Created using Sphinx' text
+html_show_sphinx = False
+
+# Add 'Last updated' on each page
+html_last_updated_fmt = '%b %d, %Y'
+
+# Remove the trailing 'dot' in section numbers
+html_secnumber_suffix = " "
diff --git a/bitbake/doc/genindex.rst b/bitbake/doc/genindex.rst
new file mode 100644
index 00000000..a4af06f6
--- /dev/null
+++ b/bitbake/doc/genindex.rst
@@ -0,0 +1,3 @@
+=====
+Index
+=====
diff --git a/bitbake/doc/index.rst b/bitbake/doc/index.rst
new file mode 100644
index 00000000..3ff8b158
--- /dev/null
+++ b/bitbake/doc/index.rst
@@ -0,0 +1,38 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+===================
+BitBake User Manual
+===================
+
+|
+
+.. toctree::
+   :caption: Table of Contents
+   :numbered:
+
+   bitbake-user-manual/bitbake-user-manual-intro
+   bitbake-user-manual/bitbake-user-manual-execution
+   bitbake-user-manual/bitbake-user-manual-metadata
+   bitbake-user-manual/bitbake-user-manual-fetching
+   bitbake-user-manual/bitbake-user-manual-ref-variables
+   bitbake-user-manual/bitbake-user-manual-hello
+
+.. toctree::
+   :maxdepth: 1
+   :hidden:
+
+   genindex
+   releases
+
+----
+
+.. include:: <xhtml1-lat1.txt>
+
+| BitBake Community
+| Copyright |copy| |copyright|
+| <bitbake-devel@lists.openembedded.org>
+
+This work is licensed under the Creative Commons Attribution License.  To view a
+copy of this license, visit http://creativecommons.org/licenses/by/2.5/ or send
+a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
+California 94041, USA.
diff --git a/bitbake/doc/poky.ent b/bitbake/doc/poky.ent
deleted file mode 100644
index 85d9c83b..00000000
--- a/bitbake/doc/poky.ent
+++ /dev/null
@@ -1,51 +0,0 @@
-<!ENTITY DISTRO "1.4">
-<!ENTITY DISTRO_NAME "tbd">
-<!ENTITY YOCTO_DOC_VERSION "1.4">
-<!ENTITY POKYVERSION "8.0">
-<!ENTITY YOCTO_POKY "poky-&DISTRO_NAME;-&POKYVERSION;">
-<!ENTITY COPYRIGHT_YEAR "2010-2013">
-<!ENTITY YOCTO_DL_URL "http://downloads.yoctoproject.org">
-<!ENTITY YOCTO_HOME_URL "http://www.yoctoproject.org">
-<!ENTITY YOCTO_LISTS_URL "http://lists.yoctoproject.org">
-<!ENTITY YOCTO_BUGZILLA_URL "http://bugzilla.yoctoproject.org">
-<!ENTITY YOCTO_WIKI_URL "https://wiki.yoctoproject.org">
-<!ENTITY YOCTO_AB_URL "http://autobuilder.yoctoproject.org">
-<!ENTITY YOCTO_GIT_URL "http://git.yoctoproject.org">
-<!ENTITY YOCTO_ADTREPO_URL "http://adtrepo.yoctoproject.org">
-<!ENTITY OE_HOME_URL "http://www.openembedded.org">
-<!ENTITY OE_LISTS_URL "http://lists.linuxtogo.org/cgi-bin/mailman">
-<!ENTITY OE_DOCS_URL "http://docs.openembedded.org">
-<!ENTITY OH_HOME_URL "http://o-hand.com">
-<!ENTITY BITBAKE_HOME_URL "http://developer.berlios.de/projects/bitbake/">
-<!ENTITY YOCTO_DOCS_URL "&YOCTO_HOME_URL;/docs">
-<!ENTITY YOCTO_SOURCES_URL "&YOCTO_HOME_URL;/sources/">
-<!ENTITY YOCTO_AB_PORT_URL "&YOCTO_AB_URL;:8010">
-<!ENTITY YOCTO_AB_NIGHTLY_URL "&YOCTO_AB_URL;/nightly/">
-<!ENTITY YOCTO_POKY_URL "&YOCTO_DL_URL;/releases/poky/">
-<!ENTITY YOCTO_RELEASE_DL_URL "&YOCTO_DL_URL;/releases/yocto/yocto-&DISTRO;">
-<!ENTITY YOCTO_TOOLCHAIN_DL_URL "&YOCTO_RELEASE_DL_URL;/toolchain/">
-<!ENTITY YOCTO_ADTINSTALLER_DL_URL "&YOCTO_RELEASE_DL_URL;/adt_installer">
-<!ENTITY YOCTO_POKY_DL_URL "&YOCTO_RELEASE_DL_URL;/&YOCTO_POKY;.tar.bz2">
-<!ENTITY YOCTO_MACHINES_DL_URL "&YOCTO_RELEASE_DL_URL;/machines">
-<!ENTITY YOCTO_QEMU_DL_URL "&YOCTO_MACHINES_DL_URL;/qemu">
-<!ENTITY YOCTO_PYTHON-i686_DL_URL "&YOCTO_DL_URL;/releases/miscsupport/python-nativesdk-standalone-i686.tar.bz2">
-<!ENTITY YOCTO_PYTHON-x86_64_DL_URL "&YOCTO_DL_URL;/releases/miscsupport/python-nativesdk-standalone-x86_64.tar.bz2">
-<!ENTITY YOCTO_DOCS_QS_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/yocto-project-qs/yocto-project-qs.html">
-<!ENTITY YOCTO_DOCS_ADT_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/adt-manual/adt-manual.html">
-<!ENTITY YOCTO_DOCS_REF_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/ref-manual/ref-manual.html">
-<!ENTITY YOCTO_DOCS_BSP_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/bsp-guide/bsp-guide.html">
-<!ENTITY YOCTO_DOCS_DEV_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/dev-manual/dev-manual.html">
-<!ENTITY YOCTO_DOCS_KERNEL_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/kernel-manual/kernel-manual.html">
-<!ENTITY YOCTO_ADTPATH_DIR "/opt/poky/&DISTRO;">
-<!ENTITY YOCTO_POKY_TARBALL "&YOCTO_POKY;.tar.bz2">
-<!ENTITY OE_INIT_PATH "&YOCTO_POKY;/oe-init-build-env">
-<!ENTITY OE_INIT_FILE "oe-init-build-env">
-<!ENTITY UBUNTU_HOST_PACKAGES_ESSENTIAL "gawk wget git-core diffstat unzip texinfo \
-     build-essential chrpath">
-<!ENTITY FEDORA_HOST_PACKAGES_ESSENTIAL "gawk make wget tar bzip2 gzip python unzip perl patch \
-     diffutils diffstat git cpp gcc gcc-c++ eglibc-devel texinfo chrpath \
-     ccache">
-<!ENTITY OPENSUSE_HOST_PACKAGES_ESSENTIAL "python gcc gcc-c++ git chrpath make wget python-xml \
-     diffstat texinfo python-curses">
-<!ENTITY CENTOS_HOST_PACKAGES_ESSENTIAL "gawk make wget tar bzip2 gzip python unzip perl patch \
-     diffutils diffstat git cpp gcc gcc-c++ glibc-devel texinfo chrpath">
diff --git a/bitbake/doc/releases.rst b/bitbake/doc/releases.rst
new file mode 100644
index 00000000..d68d7159
--- /dev/null
+++ b/bitbake/doc/releases.rst
@@ -0,0 +1,130 @@
+.. SPDX-License-Identifier: CC-BY-2.5
+
+=========================
+ Current Release Manuals
+=========================
+
+****************************
+3.1 'dunfell' Release Series
+****************************
+
+- :yocto_docs:`3.1 BitBake User Manual </3.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`3.1.1 BitBake User Manual </3.1.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`3.1.2 BitBake User Manual </3.1.2/bitbake-user-manual/bitbake-user-manual.html>`
+
+==========================
+ Previous Release Manuals
+==========================
+
+*************************
+3.0 'zeus' Release Series
+*************************
+
+- :yocto_docs:`3.0 BitBake User Manual </3.0/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`3.0.1 BitBake User Manual </3.0.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`3.0.2 BitBake User Manual </3.0.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`3.0.3 BitBake User Manual </3.0.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+****************************
+2.7 'warrior' Release Series
+****************************
+
+- :yocto_docs:`2.7 BitBake User Manual </2.7/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.7.1 BitBake User Manual </2.7.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.7.2 BitBake User Manual </2.7.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.7.3 BitBake User Manual </2.7.3/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.7.4 BitBake User Manual </2.7.4/bitbake-user-manual/bitbake-user-manual.html>`
+
+*************************
+2.6 'thud' Release Series
+*************************
+
+- :yocto_docs:`2.6 BitBake User Manual </2.6/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.6.1 BitBake User Manual </2.6.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.6.2 BitBake User Manual </2.6.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.6.3 BitBake User Manual </2.6.3/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.6.4 BitBake User Manual </2.6.4/bitbake-user-manual/bitbake-user-manual.html>`
+
+*************************
+2.5 'sumo' Release Series
+*************************
+
+- :yocto_docs:`2.5 BitBake User Manual </2.5/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.5.1 BitBake User Manual </2.5.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.5.2 BitBake User Manual </2.5.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.5.3 BitBake User Manual </2.5.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+**************************
+2.4 'rocko' Release Series
+**************************
+
+- :yocto_docs:`2.4 BitBake User Manual </2.4/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.4.1 BitBake User Manual </2.4.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.4.2 BitBake User Manual </2.4.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.4.3 BitBake User Manual </2.4.3/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.4.4 BitBake User Manual </2.4.4/bitbake-user-manual/bitbake-user-manual.html>`
+
+*************************
+2.3 'pyro' Release Series
+*************************
+
+- :yocto_docs:`2.3 BitBake User Manual </2.3/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.3.1 BitBake User Manual </2.3.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.3.2 BitBake User Manual </2.3.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.3.3 BitBake User Manual </2.3.3/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.3.4 BitBake User Manual </2.3.4/bitbake-user-manual/bitbake-user-manual.html>`
+
+**************************
+2.2 'morty' Release Series
+**************************
+
+- :yocto_docs:`2.2 BitBake User Manual </2.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.2.1 BitBake User Manual </2.2.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.2.2 BitBake User Manual </2.2.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.2.3 BitBake User Manual </2.2.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+****************************
+2.1 'krogoth' Release Series
+****************************
+
+- :yocto_docs:`2.1 BitBake User Manual </2.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.1.1 BitBake User Manual </2.1.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.1.2 BitBake User Manual </2.1.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.1.3 BitBake User Manual </2.1.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+***************************
+2.0 'jethro' Release Series
+***************************
+
+- :yocto_docs:`1.9 BitBake User Manual </1.9/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.0 BitBake User Manual </2.0/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.0.1 BitBake User Manual </2.0.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.0.2 BitBake User Manual </2.0.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`2.0.3 BitBake User Manual </2.0.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+*************************
+1.8 'fido' Release Series
+*************************
+
+- :yocto_docs:`1.8 BitBake User Manual </1.8/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.8.1 BitBake User Manual </1.8.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.8.2 BitBake User Manual </1.8.2/bitbake-user-manual/bitbake-user-manual.html>`
+
+**************************
+1.7 'dizzy' Release Series
+**************************
+
+- :yocto_docs:`1.7 BitBake User Manual </1.7/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.7.1 BitBake User Manual </1.7.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.7.2 BitBake User Manual </1.7.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.7.3 BitBake User Manual </1.7.3/bitbake-user-manual/bitbake-user-manual.html>`
+
+**************************
+1.6 'daisy' Release Series
+**************************
+
+- :yocto_docs:`1.6 BitBake User Manual </1.6/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.6.1 BitBake User Manual </1.6.1/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.6.2 BitBake User Manual </1.6.2/bitbake-user-manual/bitbake-user-manual.html>`
+- :yocto_docs:`1.6.3 BitBake User Manual </1.6.3/bitbake-user-manual/bitbake-user-manual.html>`
+
diff --git a/bitbake/doc/sphinx-static/switchers.js b/bitbake/doc/sphinx-static/switchers.js
new file mode 100644
index 00000000..32113cfa
--- /dev/null
+++ b/bitbake/doc/sphinx-static/switchers.js
@@ -0,0 +1,233 @@
+(function() {
+  'use strict';
+
+  var all_versions = {
+    'dev': 'dev (3.2)',
+    '3.1.2': '3.1.2',
+    '3.0.3': '3.0.3',
+    '2.7.4': '2.7.4',
+  };
+
+  var all_doctypes = {
+      'single': 'Individual Webpages',
+      'mega': "All-in-one 'Mega' Manual",
+  };
+
+  // Simple version comparision
+  // Return 1 if a > b
+  // Return -1 if a < b
+  // Return 0 if a == b
+  function ver_compare(a, b) {
+    if (a == "dev") {
+       return 1;
+    }
+
+    if (a === b) {
+       return 0;
+    }
+
+    var a_components = a.split(".");
+    var b_components = b.split(".");
+
+    var len = Math.min(a_components.length, b_components.length);
+
+    // loop while the components are equal
+    for (var i = 0; i < len; i++) {
+        // A bigger than B
+        if (parseInt(a_components[i]) > parseInt(b_components[i])) {
+            return 1;
+        }
+
+        // B bigger than A
+        if (parseInt(a_components[i]) < parseInt(b_components[i])) {
+            return -1;
+        }
+    }
+
+    // If one's a prefix of the other, the longer one is greater.
+    if (a_components.length > b_components.length) {
+        return 1;
+    }
+
+    if (a_components.length < b_components.length) {
+        return -1;
+    }
+
+    // Otherwise they are the same.
+    return 0;
+  }
+
+  function build_version_select(current_series, current_version) {
+    var buf = ['<select>'];
+
+    $.each(all_versions, function(version, title) {
+      var series = version.substr(0, 3);
+      if (series == current_series) {
+        if (version == current_version)
+            buf.push('<option value="' + version + '" selected="selected">' + title + '</option>');
+        else
+            buf.push('<option value="' + version + '">' + title + '</option>');
+
+        if (version != current_version)
+            buf.push('<option value="' + current_version + '" selected="selected">' + current_version + '</option>');
+      } else {
+        buf.push('<option value="' + version + '">' + title + '</option>');
+      }
+    });
+
+    buf.push('</select>');
+    return buf.join('');
+  }
+
+  function build_doctype_select(current_doctype) {
+    var buf = ['<select>'];
+
+    $.each(all_doctypes, function(doctype, title) {
+      if (doctype == current_doctype)
+        buf.push('<option value="' + doctype + '" selected="selected">' +
+                 all_doctypes[current_doctype] + '</option>');
+      else
+        buf.push('<option value="' + doctype + '">' + title + '</option>');
+    });
+    if (!(current_doctype in all_doctypes)) {
+        // In case we're browsing a doctype that is not yet in all_doctypes.
+        buf.push('<option value="' + current_doctype + '" selected="selected">' +
+                 current_doctype + '</option>');
+        all_doctypes[current_doctype] = current_doctype;
+    }
+    buf.push('</select>');
+    return buf.join('');
+  }
+
+  function navigate_to_first_existing(urls) {
+    // Navigate to the first existing URL in urls.
+    var url = urls.shift();
+
+    // Web browsers won't redirect file:// urls to file urls using ajax but
+    // its useful for local testing
+    if (url.startsWith("file://")) {
+      window.location.href = url;
+      return;
+    }
+
+    if (urls.length == 0) {
+      window.location.href = url;
+      return;
+    }
+    $.ajax({
+      url: url,
+      success: function() {
+        window.location.href = url;
+      },
+      error: function() {
+        navigate_to_first_existing(urls);
+      }
+    });
+  }
+
+  function get_docroot_url() {
+    var url = window.location.href;
+    var root = DOCUMENTATION_OPTIONS.URL_ROOT;
+
+    var urlarray = url.split('/');
+    // Trim off anything after '/'
+    urlarray.pop();
+    var depth = (root.match(/\.\.\//g) || []).length;
+    for (var i = 0; i < depth; i++) {
+      urlarray.pop();
+    }
+
+    return urlarray.join('/') + '/';
+  }
+
+  function on_version_switch() {
+    var selected_version = $(this).children('option:selected').attr('value');
+    var url = window.location.href;
+    var current_version = DOCUMENTATION_OPTIONS.VERSION;
+    var docroot = get_docroot_url()
+
+    var new_versionpath = selected_version + '/';
+    if (selected_version == "dev")
+        new_versionpath = '';
+
+    // dev versions have no version prefix
+    if (current_version == "dev") {
+        var new_url = docroot + new_versionpath + url.replace(docroot, "");
+        var fallback_url = docroot + new_versionpath;
+    } else {
+        var new_url = url.replace('/' + current_version + '/', '/' + new_versionpath);
+        var fallback_url = new_url.replace(url.replace(docroot, ""), "");
+    }
+
+    console.log(get_docroot_url())
+    console.log(url + " to url " + new_url);
+    console.log(url + " to fallback " + fallback_url);
+
+    if (new_url != url) {
+      navigate_to_first_existing([
+        new_url,
+        fallback_url,
+        'https://www.yoctoproject.org/docs/',
+      ]);
+    }
+  }
+
+  function on_doctype_switch() {
+    var selected_doctype = $(this).children('option:selected').attr('value');
+    var url = window.location.href;
+    if (selected_doctype == 'mega') {
+      var docroot = get_docroot_url()
+      var current_version = DOCUMENTATION_OPTIONS.VERSION;
+      // Assume manuals before 3.2 are using old docbook mega-manual
+      if (ver_compare(current_version, "3.2") < 0) {
+        var new_url = docroot + "mega-manual/mega-manual.html";
+      } else {
+        var new_url = docroot + "singleindex.html";
+      }
+    } else {
+      var new_url = url.replace("singleindex.html", "index.html")
+    }
+
+    if (new_url != url) {
+      navigate_to_first_existing([
+        new_url,
+        'https://www.yoctoproject.org/docs/',
+      ]);
+    }
+  }
+
+  // Returns the current doctype based upon the url
+  function doctype_segment_from_url(url) {
+    if (url.includes("singleindex") || url.includes("mega-manual"))
+      return "mega";
+    return "single";
+  }
+
+  $(document).ready(function() {
+    var release = DOCUMENTATION_OPTIONS.VERSION;
+    var current_doctype = doctype_segment_from_url(window.location.href);
+    var current_series = release.substr(0, 3);
+    var version_select = build_version_select(current_series, release);
+
+    $('.version_switcher_placeholder').html(version_select);
+    $('.version_switcher_placeholder select').bind('change', on_version_switch);
+
+    var doctype_select = build_doctype_select(current_doctype);
+
+    $('.doctype_switcher_placeholder').html(doctype_select);
+    $('.doctype_switcher_placeholder select').bind('change', on_doctype_switch);
+
+    if (ver_compare(release, "3.1") < 0) {
+      $('#outdated-warning').html('Version ' + release + ' of the project is now considered obsolete, please select and use a more recent version');
+      $('#outdated-warning').css('padding', '.5em');
+    } else if (release != "dev") {
+      $.each(all_versions, function(version, title) {
+        var series = version.substr(0, 3);
+        if (series == current_series && version != release) {
+          $('#outdated-warning').html('This document is for outdated version ' + release + ', you should select the latest release version in this series, ' + version + '.');
+          $('#outdated-warning').css('padding', '.5em');
+        }
+      });
+    }
+  });
+})();
diff --git a/bitbake/doc/sphinx-static/theme_overrides.css b/bitbake/doc/sphinx-static/theme_overrides.css
new file mode 100644
index 00000000..e362677a
--- /dev/null
+++ b/bitbake/doc/sphinx-static/theme_overrides.css
@@ -0,0 +1,162 @@
+/*
+    SPDX-License-Identifier: CC-BY-2.0-UK
+*/
+
+body {
+  font-family: Verdana, Sans, sans-serif;
+  margin:  0em auto;
+  color: #333;
+}
+
+h1,h2,h3,h4,h5,h6,h7 {
+  font-family: Arial, Sans;
+  color: #00557D;
+  clear: both;
+}
+
+h1 {
+  font-size: 2em;
+  text-align: left;
+  padding: 0em 0em 0em 0em;
+  margin: 2em 0em 0em 0em;
+}
+
+h2.subtitle {
+  margin: 0.10em 0em 3.0em 0em;
+  padding: 0em 0em 0em 0em;
+  font-size: 1.8em;
+  padding-left: 20%;
+  font-weight: normal;
+  font-style: italic;
+}
+
+h2 {
+  margin: 2em 0em 0.66em 0em;
+  padding: 0.5em 0em 0em 0em;
+  font-size: 1.5em;
+  font-weight: bold;
+}
+
+h3.subtitle {
+  margin: 0em 0em 1em 0em;
+  padding: 0em 0em 0em 0em;
+  font-size: 142.14%;
+  text-align: right;
+}
+
+h3 {
+  margin: 1em 0em 0.5em 0em;
+  padding: 1em 0em 0em 0em;
+  font-size: 140%;
+  font-weight: bold;
+}
+
+h4 {
+  margin: 1em 0em 0.5em 0em;
+  padding: 1em 0em 0em 0em;
+  font-size: 120%;
+  font-weight: bold;
+}
+
+h5 {
+  margin: 1em 0em 0.5em 0em;
+  padding: 1em 0em 0em 0em;
+  font-size: 110%;
+  font-weight: bold;
+}
+
+h6 {
+  margin: 1em 0em 0em 0em;
+  padding: 1em 0em 0em 0em;
+  font-size: 110%;
+  font-weight: bold;
+}
+
+em {
+  font-weight: bold;
+}
+
+.pre {
+  font-size: medium;
+  font-family: Courier, monospace;
+}
+
+.wy-nav-content a {
+  text-decoration: underline;
+  color: #444;
+  background: transparent;
+}
+
+.wy-nav-content a:hover {
+  text-decoration: underline;
+  background-color: #dedede;
+}
+
+.wy-nav-content a:visited {
+  color: #444;
+}
+
+[alt='Permalink'] { color: #eee; }
+[alt='Permalink']:hover { color: black; }
+
+@media screen {
+    /* content column
+     *
+     * RTD theme's default is 800px as max width for the content, but we have
+     * tables with tons of columns, which need the full width of the view-port.
+     */
+
+    .wy-nav-content{max-width: none; }
+
+    /* inline literal: drop the borderbox, padding and red color */
+    code, .rst-content tt, .rst-content code {
+        color: inherit;
+        border: none;
+        padding: unset;
+        background: inherit;
+        font-size: 85%;
+    }
+
+    .rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
+        color: inherit;
+    }
+
+    /* Admonition should be gray, not blue or green */
+    .rst-content .note .admonition-title,
+    .rst-content .tip .admonition-title,
+    .rst-content .warning .admonition-title,
+    .rst-content .caution .admonition-title,
+    .rst-content .important .admonition-title {
+        background: #f0f0f2;
+        color: #00557D;
+
+    }
+
+    .rst-content .note,
+    .rst-content .tip,
+    .rst-content .important,
+    .rst-content .warning,
+    .rst-content .caution  {
+        background: #f0f0f2;
+    }
+
+    /* Remove the icon in front of note/tip element, and before the logo */
+    .icon-home:before, .rst-content .admonition-title:before {
+        display: none
+    }
+
+    /* a custom informalexample container is used in some doc */
+    .informalexample {
+        border: 1px solid;
+        border-color: #aaa;
+        margin: 1em 0em;
+        padding: 1em;
+        page-break-inside: avoid;
+    }
+
+    /* Remove the blue background in the top left corner, around the logo */
+    .wy-side-nav-search {
+        background: inherit;
+    }
+
+}
diff --git a/bitbake/doc/template/Vera.xml b/bitbake/doc/template/Vera.xml
deleted file mode 100644
index 3c82043e..00000000
--- a/bitbake/doc/template/Vera.xml
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><font-metrics type="TYPE0"><font-name>BitstreamVeraSans</font-name><embed/><cap-height>729</cap-height><x-height>546</x-height><ascender>928</ascender><descender>-235</descender><bbox><left>-183</left><bottom>-235</bottom><right>1287</right><top>928</top></bbox><flags>32</flags><stemv>0</stemv><italicangle>0</italicangle><subtype>TYPE0</subtype><multibyte-extras><cid-type>CIDFontType2</cid-type><default-width>0</default-width><bfranges><bf gi="3" ue="126" us="32"/><bf gi="172" ue="160" us="160"/><bf gi="163" ue="161" us="161"/><bf gi="132" ue="163" us="162"/><bf gi="189" ue="164" us="164"/><bf gi="150" ue="165" us="165"/><bf gi="231" ue="166" us="166"/><bf gi="134" ue="167" us="167"/><bf gi="142" ue="168" us="168"/><bf gi="139" ue="169" us="169"/><bf gi="157" ue="170" us="170"/><bf gi="169" ue="171" us="171"/><bf gi="164" ue="172" us="172"/><bf gi="256" ue="173" us="173"/><bf gi="138" ue="174" us="174"/><bf gi="217" ue="175" us="175"/><bf gi="131" ue="176" us="176"/><bf gi="147" ue="177" us="177"/><bf gi="241" ue="179" us="178"/><bf gi="141" ue="180" us="180"/><bf gi="151" ue="181" us="181"/><bf gi="136" ue="182" us="182"/><bf gi="195" ue="183" us="183"/><bf gi="221" ue="184" us="184"/><bf gi="240" ue="185" us="185"/><bf gi="158" ue="186" us="186"/><bf gi="170" ue="187" us="187"/><bf gi="243" ue="190" us="188"/><bf gi="162" ue="191" us="191"/><bf gi="173" ue="192" us="192"/><bf gi="201" ue="193" us="193"/><bf gi="199" ue="194" us="194"/><bf gi="174" ue="195" us="195"/><bf gi="98" ue="197" us="196"/><bf gi="144" ue="198" us="198"/><bf gi="100" ue="199" us="199"/><bf gi="203" ue="200" us="200"/><bf gi="101" ue="201" us="201"/><bf gi="200" ue="202" us="202"/><bf gi="202" ue="203" us="203"/><bf gi="207" ue="204" us="204"/><bf gi="204" ue="207" us="205"/><bf gi="232" ue="208" us="208"/><bf gi="102" ue="209" us="209"/><bf gi="210" ue="210" us="210"/><bf gi="208" ue="212" us="211"/><bf gi="175" ue="213" us="213"/><bf gi="103" ue="214" us="214"/><bf gi="239" ue="215" us="215"/><bf gi="145" ue="216" us="216"/><bf gi="213" ue="217" us="217"/><bf gi="211" ue="219" us="218"/><bf gi="104" ue="220" us="220"/><bf gi="234" ue="221" us="221"/><bf gi="236" ue="222" us="222"/><bf gi="137" ue="223" us="223"/><bf gi="106" ue="224" us="224"/><bf gi="105" ue="225" us="225"/><bf gi="107" ue="226" us="226"/><bf gi="109" ue="227" us="227"/><bf gi="108" ue="228" us="228"/><bf gi="110" ue="229" us="229"/><bf gi="160" ue="230" us="230"/><bf gi="111" ue="231" us="231"/><bf gi="113" ue="232" us="232"/><bf gi="112" ue="233" us="233"/><bf gi="114" ue="235" us="234"/><bf gi="117" ue="236" us="236"/><bf gi="116" ue="237" us="237"/><bf gi="118" ue="239" us="238"/><bf gi="233" ue="240" us="240"/><bf gi="120" ue="241" us="241"/><bf gi="122" ue="242" us="242"/><bf gi="121" ue="243" us="243"/><bf gi="123" ue="244" us="244"/><bf gi="125" ue="245" us="245"/><bf gi="124" ue="246" us="246"/><bf gi="184" ue="247" us="247"/><bf gi="161" ue="248" us="248"/><bf gi="127" ue="249" us="249"/><bf gi="126" ue="250" us="250"/><bf gi="128" ue="252" us="251"/><bf gi="235" ue="253" us="253"/><bf gi="237" ue="254" us="254"/><bf gi="186" ue="255" us="255"/><bf gi="251" ue="263" us="262"/><bf gi="253" ue="269" us="268"/><bf gi="0" ue="270" us="270"/><bf gi="0" ue="271" us="271"/><bf gi="0" ue="272" us="272"/><bf gi="255" ue="273" us="273"/><bf gi="246" ue="287" us="286"/><bf gi="248" ue="304" us="304"/><bf gi="214" ue="305" us="305"/><bf gi="225" ue="322" us="321"/><bf gi="176" ue="339" us="338"/><bf gi="249" ue="351" us="350"/><bf gi="227" ue="353" us="352"/><bf gi="187" ue="376" us="376"/><bf gi="229" ue="382" us="381"/><bf gi="166" ue="402" us="402"/><bf gi="215" ue="710" us="710"/><bf gi="224" ue="711" us="711"/><bf gi="218" ue="730" us="728"/><bf gi="223" ue="731" us="731"/><bf gi="216" ue="732" us="732"/><bf gi="222" ue="733" us="733"/><bf gi="159" ue="937" us="937"/><bf gi="155" ue="960" us="960"/><bf gi="178" ue="8212" us="8211"/><bf gi="0" ue="8213" us="8213"/><bf gi="0" ue="8214" us="8214"/><bf gi="0" ue="8215" us="8215"/><bf gi="182" ue="8217" us="8216"/><bf gi="196" ue="8218" us="8218"/><bf gi="0" ue="8219" us="8219"/><bf gi="180" ue="8221" us="8220"/><bf gi="197" ue="8222" us="8222"/><bf gi="0" ue="8223" us="8223"/><bf gi="130" ue="8224" us="8224"/><bf gi="194" ue="8225" us="8225"/><bf gi="135" ue="8226" us="8226"/><bf gi="0" ue="8227" us="8227"/><bf gi="0" ue="8228" us="8228"/><bf gi="0" ue="8229" us="8229"/><bf gi="171" ue="8230" us="8230"/><bf gi="198" ue="8240" us="8240"/><bf gi="190" ue="8250" us="8249"/><bf gi="258" ue="8364" us="8364"/><bf gi="140" ue="8482" us="8482"/><bf gi="152" ue="8706" us="8706"/><bf gi="0" ue="8707" us="8707"/><bf gi="0" ue="8708" us="8708"/><bf gi="0" ue="8709" us="8709"/><bf gi="168" ue="8710" us="8710"/><bf gi="154" ue="8719" us="8719"/><bf gi="0" ue="8720" us="8720"/><bf gi="153" ue="8721" us="8721"/><bf gi="238" ue="8722" us="8722"/><bf gi="0" ue="8723" us="8723"/><bf gi="0" ue="8724" us="8724"/><bf gi="188" ue="8725" us="8725"/><bf gi="0" ue="8726" us="8726"/><bf gi="0" ue="8727" us="8727"/><bf gi="0" ue="8728" us="8728"/><bf gi="257" ue="8729" us="8729"/><bf gi="165" ue="8730" us="8730"/><bf gi="0" ue="8731" us="8731"/><bf gi="0" ue="8732" us="8732"/><bf gi="0" ue="8733" us="8733"/><bf gi="146" ue="8734" us="8734"/><bf gi="156" ue="8747" us="8747"/><bf gi="167" ue="8776" us="8776"/><bf gi="143" ue="8800" us="8800"/><bf gi="0" ue="8801" us="8801"/><bf gi="0" ue="8802" us="8802"/><bf gi="0" ue="8803" us="8803"/><bf gi="148" ue="8805" us="8804"/><bf gi="185" ue="9674" us="9674"/><bf gi="192" ue="64258" us="64257"/><bf gi="0" ue="65535" us="65535"/></bfranges><cid-widths start-index="0"><wx w="600"/><wx w="0"/><wx w="317"/><wx w="317"/><wx w="400"/><wx w="459"/><wx w="837"/><wx w="636"/><wx w="950"/><wx w="779"/><wx w="274"/><wx w="390"/><wx w="390"/><wx w="500"/><wx w="837"/><wx w="317"/><wx w="360"/><wx w="317"/><wx w="336"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="636"/><wx w="336"/><wx w="336"/><wx w="837"/><wx w="837"/><wx w="837"/><wx w="530"/><wx w="1000"/><wx w="684"/><wx w="686"/><wx w="698"/><wx w="770"/><wx w="631"/><wx w="575"/><wx w="774"/><wx w="751"/><wx w="294"/><wx w="294"/><wx w="655"/><wx w="557"/><wx w="862"/><wx w="748"/><wx w="787"/><wx w="603"/><wx w="787"/><wx w="694"/><wx w="634"/><wx w="610"/><wx w="731"/><wx w="684"/><wx w="988"/><wx w="685"/><wx w="610"/><wx w="685"/><wx w="390"/><wx w="336"/><wx w="390"/><wx w="837"/><wx w="500"/><wx w="500"/><wx w="612"/><wx w="634"/><wx w="549"/><wx w="634"/><wx w="615"/><wx w="352"/><wx w="634"/><wx w="633"/><wx w="277"/><wx w="277"/><wx w="579"/><wx w="277"/><wx w="974"/><wx w="633"/><wx w="611"/><wx w="634"/><wx w="634"/><wx w="411"/><wx w="520"/><wx w="392"/><wx w="633"/><wx w="591"/><wx w="817"/><wx w="591"/><wx w="591"/><wx w="524"/><wx w="636"/><wx w="336"/><wx w="636"/><wx w="837"/><wx w="684"/><wx w="684"/><wx w="698"/><wx w="631"/><wx w="748"/><wx w="787"/><wx w="731"/><wx w="612"/><wx w="612"/><wx w="612"/><wx w="612"/><wx w="612"/><wx w="612"/><wx w="549"/><wx w="615"/><wx w="615"/><wx w="615"/><wx w="615"/><wx w="277"/><wx w="277"/><wx w="277"/><wx w="277"/><wx w="633"/><wx w="611"/><wx w="611"/><wx w="611"/><wx w="611"/><wx w="611"/><wx w="633"/><wx w="633"/><wx w="633"/><wx w="633"/><wx w="500"/><wx w="500"/><wx w="636"/><wx w="636"/><wx w="500"/><wx w="589"/><wx w="636"/><wx w="629"/><wx w="1000"/><wx w="1000"/><wx w="1000"/><wx w="500"/><wx w="500"/><wx w="837"/><wx w="974"/><wx w="787"/><wx w="833"/><wx w="837"/><wx w="837"/><wx w="837"/><wx w="636"/><wx w="636"/><wx w="517"/><wx w="673"/><wx w="756"/><wx w="588"/><wx w="520"/><wx w="471"/><wx w="471"/><wx w="764"/><wx w="981"/><wx w="611"/><wx w="530"/><wx w="400"/><wx w="837"/><wx w="637"/><wx w="636"/><wx w="837"/><wx w="668"/><wx w="611"/><wx w="611"/><wx w="1000"/><wx w="636"/><wx w="684"/><wx w="684"/><wx w="787"/><wx w="1069"/><wx w="1022"/><wx w="500"/><wx w="1000"/><wx w="518"/><wx w="518"/><wx w="317"/><wx w="317"/><wx w="837"/><wx w="494"/><wx w="591"/><wx w="610"/><wx w="166"/><wx w="636"/><wx w="399"/><wx w="399"/><wx w="629"/><wx w="629"/><wx w="500"/><wx w="317"/><wx w="317"/><wx w="518"/><wx w="1341"/><wx w="684"/><wx w="631"/><wx w="684"/><wx w="631"/><wx w="631"/><wx w="294"/><wx w="294"/><wx w="294"/><wx w="294"/><wx w="787"/><wx w="787"/><wx w="787"/><wx w="731"/><wx w="731"/><wx w="731"/><wx w="277"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="562"/><wx w="284"/><wx w="634"/><wx w="520"/><wx w="685"/><wx w="524"/><wx w="336"/><wx w="774"/><wx w="611"/><wx w="610"/><wx w="591"/><wx w="604"/><wx w="634"/><wx w="837"/><wx w="837"/><wx w="400"/><wx w="400"/><wx w="400"/><wx w="969"/><wx w="969"/><wx w="969"/><wx w="774"/><wx w="634"/><wx w="294"/><wx w="634"/><wx w="520"/><wx w="698"/><wx w="549"/><wx w="698"/><wx w="549"/><wx w="634"/><wx w="360"/><wx w="317"/><wx w="636"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="500"/><wx w="400"/><wx w="500"/><wx w="500"/></cid-widths></multibyte-extras><kerning kpx1="246"><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="169"/><pair kern="-26" kpx2="197"/><pair kern="-35" kpx2="55"/><pair kern="-49" kpx2="60"/><pair kern="-49" kpx2="187"/><pair kern="-21" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-49" kpx2="234"/></kerning><kerning kpx1="235"><pair kern="-142" kpx2="17"/><pair kern="-17" kpx2="169"/><pair kern="-146" kpx2="197"/><pair kern="-17" kpx2="16"/><pair kern="-72" kpx2="29"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="43"><pair kern="-35" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-35" kpx2="197"/><pair kern="-30" kpx2="181"/></kerning><kerning kpx1="16"><pair kern="36" kpx2="246"/><pair kern="-17" kpx2="235"/><pair kern="-21" kpx2="199"/><pair kern="18" kpx2="123"/><pair kern="27" kpx2="208"/><pair kern="-118" kpx2="187"/><pair kern="-49" kpx2="59"/><pair kern="18" kpx2="124"/><pair kern="-21" kpx2="201"/><pair kern="-118" kpx2="60"/><pair kern="36" kpx2="52"/><pair kern="18" kpx2="125"/><pair kern="36" kpx2="42"/><pair kern="-118" kpx2="234"/><pair kern="18" kpx2="122"/><pair kern="27" kpx2="210"/><pair kern="-21" kpx2="36"/><pair kern="18" kpx2="82"/><pair kern="-40" kpx2="58"/><pair kern="-91" kpx2="55"/><pair kern="-17" kpx2="186"/><pair kern="27" kpx2="175"/><pair kern="27" kpx2="50"/><pair kern="27" kpx2="209"/><pair kern="27" kpx2="103"/><pair kern="-21" kpx2="98"/><pair kern="55" kpx2="45"/><pair kern="-21" kpx2="173"/><pair kern="-17" kpx2="92"/><pair kern="-26" kpx2="89"/><pair kern="18" kpx2="121"/><pair kern="-58" kpx2="57"/><pair kern="-35" kpx2="37"/><pair kern="-21" kpx2="174"/></kerning><kerning kpx1="112"><pair kern="-17" kpx2="91"/></kerning><kerning kpx1="123"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="251"><pair kern="-17" kpx2="169"/><pair kern="-17" kpx2="60"/><pair kern="-17" kpx2="187"/><pair kern="18" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-17" kpx2="234"/></kerning><kerning kpx1="213"><pair kern="-17" kpx2="229"/><pair kern="-17" kpx2="61"/></kerning><kerning kpx1="208"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="187"><pair kern="-114" kpx2="126"/><pair kern="-137" kpx2="107"/><pair kern="-132" kpx2="72"/><pair kern="-77" kpx2="199"/><pair kern="-118" kpx2="16"/><pair kern="-132" kpx2="123"/><pair kern="-132" kpx2="112"/><pair kern="-54" kpx2="251"/><pair kern="-54" kpx2="208"/><pair kern="-132" kpx2="113"/><pair kern="-54" kpx2="180"/><pair kern="-137" kpx2="105"/><pair kern="-114" kpx2="129"/><pair kern="-132" kpx2="124"/><pair kern="-109" kpx2="169"/><pair kern="-77" kpx2="201"/><pair kern="-54" kpx2="253"/><pair kern="-137" kpx2="106"/><pair kern="-132" kpx2="29"/><pair kern="-132" kpx2="125"/><pair kern="-72" kpx2="170"/><pair kern="-132" kpx2="115"/><pair kern="-114" kpx2="88"/><pair kern="-132" kpx2="122"/><pair kern="-54" kpx2="100"/><pair kern="-137" kpx2="68"/><pair kern="-54" kpx2="210"/><pair kern="-77" kpx2="36"/><pair kern="-132" kpx2="82"/><pair kern="-132" kpx2="114"/><pair kern="-54" kpx2="175"/><pair kern="-114" kpx2="127"/><pair kern="-54" kpx2="50"/><pair kern="-54" kpx2="209"/><pair kern="-54" kpx2="103"/><pair kern="-137" kpx2="108"/><pair kern="-77" kpx2="98"/><pair kern="-35" kpx2="76"/><pair kern="-17" kpx2="181"/><pair kern="-202" kpx2="17"/><pair kern="-114" kpx2="128"/><pair kern="-77" kpx2="173"/><pair kern="-137" kpx2="109"/><pair kern="-128" kpx2="197"/><pair kern="-54" kpx2="38"/><pair kern="-132" kpx2="121"/><pair kern="-137" kpx2="110"/><pair kern="-77" kpx2="174"/></kerning><kerning kpx1="113"><pair kern="-17" kpx2="91"/></kerning><kerning kpx1="144"><pair kern="-40" kpx2="180"/><pair kern="-54" kpx2="197"/><pair kern="-44" kpx2="181"/></kerning><kerning kpx1="59"><pair kern="-72" kpx2="100"/><pair kern="-63" kpx2="210"/><pair kern="-17" kpx2="55"/><pair kern="-44" kpx2="114"/><pair kern="-44" kpx2="72"/><pair kern="-63" kpx2="175"/><pair kern="-49" kpx2="16"/><pair kern="-63" kpx2="50"/><pair kern="-63" kpx2="209"/><pair kern="-44" kpx2="112"/><pair kern="-72" kpx2="251"/><pair kern="-63" kpx2="103"/><pair kern="-63" kpx2="208"/><pair kern="-44" kpx2="113"/><pair kern="-40" kpx2="181"/><pair kern="-77" kpx2="180"/><pair kern="-54" kpx2="169"/><pair kern="-21" kpx2="197"/><pair kern="-72" kpx2="38"/><pair kern="-72" kpx2="253"/><pair kern="-44" kpx2="115"/></kerning><kerning kpx1="73"><pair kern="31" kpx2="180"/><pair kern="-17" kpx2="90"/><pair kern="-72" kpx2="17"/><pair kern="-17" kpx2="235"/><pair kern="-35" kpx2="169"/><pair kern="-114" kpx2="197"/><pair kern="-17" kpx2="186"/><pair kern="-17" kpx2="92"/><pair kern="-17" kpx2="87"/><pair kern="-54" kpx2="16"/><pair kern="-35" kpx2="29"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="41"><pair kern="-17" kpx2="227"/><pair kern="-54" kpx2="126"/><pair kern="-91" kpx2="107"/><pair kern="-91" kpx2="235"/><pair kern="-54" kpx2="72"/><pair kern="-91" kpx2="199"/><pair kern="-35" kpx2="123"/><pair kern="-54" kpx2="112"/><pair kern="-54" kpx2="113"/><pair kern="-17" kpx2="54"/><pair kern="-21" kpx2="180"/><pair kern="-91" kpx2="105"/><pair kern="-54" kpx2="129"/><pair kern="-35" kpx2="124"/><pair kern="-91" kpx2="201"/><pair kern="-72" kpx2="85"/><pair kern="-91" kpx2="106"/><pair kern="-77" kpx2="29"/><pair kern="-35" kpx2="125"/><pair kern="-54" kpx2="115"/><pair kern="-54" kpx2="88"/><pair kern="-35" kpx2="122"/><pair kern="-91" kpx2="68"/><pair kern="-91" kpx2="36"/><pair kern="-35" kpx2="82"/><pair kern="-91" kpx2="186"/><pair kern="-17" kpx2="55"/><pair kern="-54" kpx2="114"/><pair kern="-54" kpx2="127"/><pair kern="-91" kpx2="108"/><pair kern="-91" kpx2="98"/><pair kern="-72" kpx2="76"/><pair kern="-160" kpx2="17"/><pair kern="-54" kpx2="128"/><pair kern="-91" kpx2="173"/><pair kern="-91" kpx2="109"/><pair kern="-183" kpx2="197"/><pair kern="-91" kpx2="92"/><pair kern="-35" kpx2="121"/><pair kern="-91" kpx2="110"/><pair kern="-91" kpx2="174"/><pair kern="-17" kpx2="249"/></kerning><kerning kpx1="124"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="169"><pair kern="-17" kpx2="90"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="246"/><pair kern="-17" kpx2="235"/><pair kern="-17" kpx2="58"/><pair kern="-17" kpx2="186"/><pair kern="-54" kpx2="55"/><pair kern="-17" kpx2="251"/><pair kern="-72" kpx2="187"/><pair kern="-17" kpx2="39"/><pair kern="73" kpx2="144"/><pair kern="-17" kpx2="45"/><pair kern="-17" kpx2="92"/><pair kern="-17" kpx2="38"/><pair kern="-72" kpx2="60"/><pair kern="-17" kpx2="89"/><pair kern="-17" kpx2="253"/><pair kern="-54" kpx2="57"/><pair kern="-17" kpx2="37"/><pair kern="-17" kpx2="42"/><pair kern="-72" kpx2="234"/></kerning><kerning kpx1="201"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="60"><pair kern="-114" kpx2="126"/><pair kern="-137" kpx2="107"/><pair kern="-132" kpx2="72"/><pair kern="-77" kpx2="199"/><pair kern="-118" kpx2="16"/><pair kern="-132" kpx2="123"/><pair kern="-132" kpx2="112"/><pair kern="-54" kpx2="251"/><pair kern="-54" kpx2="208"/><pair kern="-132" kpx2="113"/><pair kern="-54" kpx2="180"/><pair kern="-137" kpx2="105"/><pair kern="-114" kpx2="129"/><pair kern="-132" kpx2="124"/><pair kern="-109" kpx2="169"/><pair kern="-77" kpx2="201"/><pair kern="-54" kpx2="253"/><pair kern="-137" kpx2="106"/><pair kern="-132" kpx2="29"/><pair kern="-132" kpx2="125"/><pair kern="-72" kpx2="170"/><pair kern="-132" kpx2="115"/><pair kern="-114" kpx2="88"/><pair kern="-132" kpx2="122"/><pair kern="-54" kpx2="100"/><pair kern="-137" kpx2="68"/><pair kern="-54" kpx2="210"/><pair kern="-77" kpx2="36"/><pair kern="-132" kpx2="82"/><pair kern="-132" kpx2="114"/><pair kern="-54" kpx2="175"/><pair kern="-114" kpx2="127"/><pair kern="-54" kpx2="50"/><pair kern="-54" kpx2="209"/><pair kern="-54" kpx2="103"/><pair kern="-137" kpx2="108"/><pair kern="-77" kpx2="98"/><pair kern="-35" kpx2="76"/><pair kern="-17" kpx2="181"/><pair kern="-202" kpx2="17"/><pair kern="-114" kpx2="128"/><pair kern="-77" kpx2="173"/><pair kern="-137" kpx2="109"/><pair kern="-128" kpx2="197"/><pair kern="-54" kpx2="38"/><pair kern="-132" kpx2="121"/><pair kern="-137" kpx2="110"/><pair kern="-77" kpx2="174"/></kerning><kerning kpx1="85"><pair kern="-21" kpx2="254"/><pair kern="-21" kpx2="72"/><pair kern="-63" kpx2="16"/><pair kern="-21" kpx2="112"/><pair kern="-21" kpx2="123"/><pair kern="-17" kpx2="80"/><pair kern="-21" kpx2="113"/><pair kern="-17" kpx2="71"/><pair kern="-21" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-21" kpx2="252"/><pair kern="-21" kpx2="70"/><pair kern="-17" kpx2="85"/><pair kern="-17" kpx2="29"/><pair kern="-21" kpx2="125"/><pair kern="-21" kpx2="115"/><pair kern="-21" kpx2="111"/><pair kern="-21" kpx2="122"/><pair kern="-21" kpx2="82"/><pair kern="-17" kpx2="75"/><pair kern="-21" kpx2="114"/><pair kern="-26" kpx2="91"/><pair kern="-17" kpx2="81"/><pair kern="41" kpx2="181"/><pair kern="-91" kpx2="17"/><pair kern="-151" kpx2="197"/><pair kern="-17" kpx2="74"/><pair kern="-17" kpx2="84"/><pair kern="-21" kpx2="121"/><pair kern="-17" kpx2="247"/><pair kern="-17" kpx2="120"/></kerning><kerning kpx1="61"><pair kern="-17" kpx2="180"/><pair kern="-17" kpx2="197"/><pair kern="-17" kpx2="16"/><pair kern="-17" kpx2="181"/></kerning><kerning kpx1="234"><pair kern="-114" kpx2="126"/><pair kern="-137" kpx2="107"/><pair kern="-132" kpx2="72"/><pair kern="-77" kpx2="199"/><pair kern="-118" kpx2="16"/><pair kern="-132" kpx2="123"/><pair kern="-132" kpx2="112"/><pair kern="-54" kpx2="251"/><pair kern="-54" kpx2="208"/><pair kern="-132" kpx2="113"/><pair kern="-54" kpx2="180"/><pair kern="-137" kpx2="105"/><pair kern="-114" kpx2="129"/><pair kern="-132" kpx2="124"/><pair kern="-109" kpx2="169"/><pair kern="-77" kpx2="201"/><pair kern="-54" kpx2="253"/><pair kern="-137" kpx2="106"/><pair kern="-132" kpx2="29"/><pair kern="-132" kpx2="125"/><pair kern="-72" kpx2="170"/><pair kern="-132" kpx2="115"/><pair kern="-114" kpx2="88"/><pair kern="-132" kpx2="122"/><pair kern="-54" kpx2="100"/><pair kern="-137" kpx2="68"/><pair kern="-54" kpx2="210"/><pair kern="-77" kpx2="36"/><pair kern="-132" kpx2="82"/><pair kern="-132" kpx2="114"/><pair kern="-54" kpx2="175"/><pair kern="-114" kpx2="127"/><pair kern="-54" kpx2="50"/><pair kern="-54" kpx2="209"/><pair kern="-54" kpx2="103"/><pair kern="-137" kpx2="108"/><pair kern="-77" kpx2="98"/><pair kern="-35" kpx2="76"/><pair kern="-17" kpx2="181"/><pair kern="-202" kpx2="17"/><pair kern="-114" kpx2="128"/><pair kern="-77" kpx2="173"/><pair kern="-137" kpx2="109"/><pair kern="-128" kpx2="197"/><pair kern="-54" kpx2="38"/><pair kern="-132" kpx2="121"/><pair kern="-137" kpx2="110"/><pair kern="-77" kpx2="174"/></kerning><kerning kpx1="100"><pair kern="-17" kpx2="169"/><pair kern="-17" kpx2="60"/><pair kern="-17" kpx2="187"/><pair kern="18" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-17" kpx2="234"/></kerning><kerning kpx1="122"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="47"><pair kern="-17" kpx2="126"/><pair kern="-91" kpx2="235"/><pair kern="-49" kpx2="104"/><pair kern="-17" kpx2="72"/><pair kern="22" kpx2="199"/><pair kern="-17" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-49" kpx2="213"/><pair kern="-35" kpx2="208"/><pair kern="-132" kpx2="187"/><pair kern="-17" kpx2="113"/><pair kern="-202" kpx2="180"/><pair kern="-17" kpx2="129"/><pair kern="-17" kpx2="124"/><pair kern="22" kpx2="201"/><pair kern="-132" kpx2="60"/><pair kern="-49" kpx2="211"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="115"/><pair kern="-132" kpx2="234"/><pair kern="-17" kpx2="88"/><pair kern="-17" kpx2="122"/><pair kern="-35" kpx2="210"/><pair kern="22" kpx2="36"/><pair kern="-17" kpx2="82"/><pair kern="-91" kpx2="58"/><pair kern="-91" kpx2="186"/><pair kern="-137" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-35" kpx2="175"/><pair kern="-17" kpx2="127"/><pair kern="-35" kpx2="50"/><pair kern="-35" kpx2="209"/><pair kern="-35" kpx2="103"/><pair kern="22" kpx2="98"/><pair kern="-262" kpx2="181"/><pair kern="-17" kpx2="128"/><pair kern="22" kpx2="173"/><pair kern="-49" kpx2="212"/><pair kern="-91" kpx2="92"/><pair kern="-17" kpx2="121"/><pair kern="-109" kpx2="57"/><pair kern="22" kpx2="174"/><pair kern="-49" kpx2="56"/></kerning><kerning kpx1="210"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="58"><pair kern="-35" kpx2="126"/><pair kern="-63" kpx2="107"/><pair kern="-17" kpx2="235"/><pair kern="-58" kpx2="72"/><pair kern="-54" kpx2="199"/><pair kern="-40" kpx2="16"/><pair kern="-58" kpx2="112"/><pair kern="-58" kpx2="123"/><pair kern="-58" kpx2="113"/><pair kern="-17" kpx2="180"/><pair kern="-63" kpx2="105"/><pair kern="-35" kpx2="129"/><pair kern="-58" kpx2="124"/><pair kern="-54" kpx2="169"/><pair kern="-54" kpx2="201"/><pair kern="-44" kpx2="85"/><pair kern="-63" kpx2="106"/><pair kern="-58" kpx2="29"/><pair kern="-58" kpx2="125"/><pair kern="-17" kpx2="170"/><pair kern="-58" kpx2="115"/><pair kern="-35" kpx2="88"/><pair kern="-58" kpx2="122"/><pair kern="-63" kpx2="68"/><pair kern="-54" kpx2="36"/><pair kern="-58" kpx2="82"/><pair kern="-17" kpx2="186"/><pair kern="-58" kpx2="114"/><pair kern="-35" kpx2="127"/><pair kern="-63" kpx2="108"/><pair kern="-54" kpx2="98"/><pair kern="-21" kpx2="76"/><pair kern="-114" kpx2="17"/><pair kern="-35" kpx2="128"/><pair kern="-54" kpx2="173"/><pair kern="-63" kpx2="109"/><pair kern="-128" kpx2="197"/><pair kern="-17" kpx2="92"/><pair kern="-58" kpx2="121"/><pair kern="-63" kpx2="110"/><pair kern="-54" kpx2="174"/></kerning><kerning kpx1="82"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="186"><pair kern="-142" kpx2="17"/><pair kern="-17" kpx2="169"/><pair kern="-146" kpx2="197"/><pair kern="-17" kpx2="16"/><pair kern="-72" kpx2="29"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="175"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="209"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="103"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="81"><pair kern="-72" kpx2="180"/><pair kern="-44" kpx2="197"/><pair kern="-54" kpx2="181"/></kerning><kerning kpx1="98"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="212"><pair kern="-17" kpx2="229"/><pair kern="-17" kpx2="61"/></kerning><kerning kpx1="229"><pair kern="-17" kpx2="180"/><pair kern="-17" kpx2="197"/><pair kern="-17" kpx2="16"/><pair kern="-17" kpx2="181"/></kerning><kerning kpx1="38"><pair kern="-17" kpx2="169"/><pair kern="-17" kpx2="60"/><pair kern="-17" kpx2="187"/><pair kern="18" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-17" kpx2="234"/></kerning><kerning kpx1="121"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="57"><pair kern="-67" kpx2="126"/><pair kern="-77" kpx2="107"/><pair kern="-26" kpx2="235"/><pair kern="-77" kpx2="72"/><pair kern="-63" kpx2="199"/><pair kern="-58" kpx2="16"/><pair kern="-77" kpx2="123"/><pair kern="-77" kpx2="112"/><pair kern="-17" kpx2="208"/><pair kern="-77" kpx2="113"/><pair kern="-77" kpx2="105"/><pair kern="-67" kpx2="129"/><pair kern="-77" kpx2="124"/><pair kern="-86" kpx2="169"/><pair kern="-63" kpx2="201"/><pair kern="-77" kpx2="106"/><pair kern="-81" kpx2="29"/><pair kern="-77" kpx2="125"/><pair kern="-54" kpx2="170"/><pair kern="-77" kpx2="115"/><pair kern="-67" kpx2="88"/><pair kern="-77" kpx2="122"/><pair kern="-77" kpx2="68"/><pair kern="-17" kpx2="210"/><pair kern="-63" kpx2="36"/><pair kern="-77" kpx2="82"/><pair kern="-26" kpx2="186"/><pair kern="-77" kpx2="114"/><pair kern="-17" kpx2="175"/><pair kern="-67" kpx2="127"/><pair kern="-17" kpx2="50"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="-77" kpx2="108"/><pair kern="-63" kpx2="98"/><pair kern="-21" kpx2="76"/><pair kern="-128" kpx2="17"/><pair kern="-67" kpx2="128"/><pair kern="-63" kpx2="173"/><pair kern="-77" kpx2="109"/><pair kern="-137" kpx2="197"/><pair kern="-26" kpx2="92"/><pair kern="-77" kpx2="121"/><pair kern="-77" kpx2="110"/><pair kern="-63" kpx2="174"/></kerning><kerning kpx1="37"><pair kern="-17" kpx2="227"/><pair kern="-17" kpx2="246"/><pair kern="-17" kpx2="251"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-17" kpx2="54"/><pair kern="-54" kpx2="180"/><pair kern="-30" kpx2="169"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="170"/><pair kern="-54" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="210"/><pair kern="-35" kpx2="58"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="50"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="-54" kpx2="181"/><pair kern="-40" kpx2="197"/><pair kern="-17" kpx2="38"/><pair kern="-30" kpx2="57"/><pair kern="-17" kpx2="249"/></kerning><kerning kpx1="120"><pair kern="-72" kpx2="180"/><pair kern="-44" kpx2="197"/><pair kern="-54" kpx2="181"/></kerning><kerning kpx1="249"><pair kern="18" kpx2="173"/><pair kern="18" kpx2="36"/><pair kern="18" kpx2="201"/><pair kern="18" kpx2="199"/><pair kern="18" kpx2="174"/><pair kern="18" kpx2="98"/></kerning><kerning kpx1="227"><pair kern="18" kpx2="173"/><pair kern="18" kpx2="36"/><pair kern="18" kpx2="201"/><pair kern="18" kpx2="199"/><pair kern="18" kpx2="174"/><pair kern="18" kpx2="98"/></kerning><kerning kpx1="51"><pair kern="-17" kpx2="126"/><pair kern="-44" kpx2="107"/><pair kern="-35" kpx2="72"/><pair kern="-63" kpx2="199"/><pair kern="-21" kpx2="16"/><pair kern="-35" kpx2="123"/><pair kern="-35" kpx2="112"/><pair kern="-21" kpx2="187"/><pair kern="-35" kpx2="113"/><pair kern="-17" kpx2="86"/><pair kern="18" kpx2="180"/><pair kern="-44" kpx2="105"/><pair kern="-17" kpx2="129"/><pair kern="-35" kpx2="124"/><pair kern="-17" kpx2="169"/><pair kern="-63" kpx2="201"/><pair kern="-17" kpx2="85"/><pair kern="-21" kpx2="60"/><pair kern="-44" kpx2="106"/><pair kern="-35" kpx2="125"/><pair kern="-35" kpx2="115"/><pair kern="-21" kpx2="234"/><pair kern="-17" kpx2="88"/><pair kern="-35" kpx2="122"/><pair kern="-44" kpx2="68"/><pair kern="-63" kpx2="36"/><pair kern="-35" kpx2="82"/><pair kern="-35" kpx2="114"/><pair kern="-17" kpx2="250"/><pair kern="-17" kpx2="127"/><pair kern="-44" kpx2="108"/><pair kern="-63" kpx2="98"/><pair kern="-17" kpx2="81"/><pair kern="-21" kpx2="76"/><pair kern="18" kpx2="181"/><pair kern="-155" kpx2="17"/><pair kern="-17" kpx2="128"/><pair kern="-63" kpx2="173"/><pair kern="-44" kpx2="109"/><pair kern="-160" kpx2="197"/><pair kern="-35" kpx2="121"/><pair kern="-17" kpx2="228"/><pair kern="-44" kpx2="110"/><pair kern="-63" kpx2="174"/><pair kern="-17" kpx2="120"/></kerning><kerning kpx1="104"><pair kern="-17" kpx2="229"/><pair kern="-17" kpx2="61"/></kerning><kerning kpx1="72"><pair kern="-17" kpx2="91"/></kerning><kerning kpx1="199"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="54"><pair kern="18" kpx2="173"/><pair kern="18" kpx2="36"/><pair kern="18" kpx2="201"/><pair kern="18" kpx2="199"/><pair kern="18" kpx2="174"/><pair kern="18" kpx2="98"/></kerning><kerning kpx1="180"><pair kern="-35" kpx2="235"/><pair kern="-35" kpx2="246"/><pair kern="-30" kpx2="43"/><pair kern="-72" kpx2="123"/><pair kern="-35" kpx2="251"/><pair kern="-35" kpx2="208"/><pair kern="-188" kpx2="144"/><pair kern="-58" kpx2="59"/><pair kern="-35" kpx2="73"/><pair kern="-30" kpx2="41"/><pair kern="-72" kpx2="124"/><pair kern="-54" kpx2="85"/><pair kern="-128" kpx2="201"/><pair kern="-17" kpx2="61"/><pair kern="-35" kpx2="100"/><pair kern="-72" kpx2="122"/><pair kern="-30" kpx2="47"/><pair kern="-35" kpx2="210"/><pair kern="-72" kpx2="82"/><pair kern="-35" kpx2="186"/><pair kern="-35" kpx2="175"/><pair kern="-35" kpx2="209"/><pair kern="-35" kpx2="103"/><pair kern="-128" kpx2="98"/><pair kern="-54" kpx2="81"/><pair kern="-17" kpx2="229"/><pair kern="-35" kpx2="38"/><pair kern="-72" kpx2="121"/><pair kern="-30" kpx2="37"/><pair kern="-54" kpx2="120"/><pair kern="-30" kpx2="51"/><pair kern="-128" kpx2="199"/><pair kern="-30" kpx2="53"/><pair kern="-30" kpx2="137"/><pair kern="-35" kpx2="233"/><pair kern="-35" kpx2="253"/><pair kern="-35" kpx2="52"/><pair kern="-72" kpx2="125"/><pair kern="-35" kpx2="42"/><pair kern="-35" kpx2="90"/><pair kern="-128" kpx2="36"/><pair kern="-35" kpx2="50"/><pair kern="-30" kpx2="39"/><pair kern="-30" kpx2="236"/><pair kern="-30" kpx2="45"/><pair kern="-128" kpx2="173"/><pair kern="-35" kpx2="92"/><pair kern="-35" kpx2="89"/><pair kern="-30" kpx2="46"/><pair kern="-128" kpx2="174"/></kerning><kerning kpx1="53"><pair kern="-21" kpx2="107"/><pair kern="-54" kpx2="235"/><pair kern="-40" kpx2="16"/><pair kern="-44" kpx2="112"/><pair kern="-44" kpx2="123"/><pair kern="-49" kpx2="251"/><pair kern="-44" kpx2="113"/><pair kern="-63" kpx2="187"/><pair kern="-44" kpx2="129"/><pair kern="-44" kpx2="124"/><pair kern="-54" kpx2="169"/><pair kern="-63" kpx2="60"/><pair kern="-40" kpx2="201"/><pair kern="-21" kpx2="106"/><pair kern="-30" kpx2="29"/><pair kern="-63" kpx2="234"/><pair kern="-49" kpx2="100"/><pair kern="-44" kpx2="122"/><pair kern="-21" kpx2="68"/><pair kern="-40" kpx2="58"/><pair kern="-44" kpx2="82"/><pair kern="-54" kpx2="186"/><pair kern="-40" kpx2="98"/><pair kern="-63" kpx2="181"/><pair kern="-35" kpx2="17"/><pair kern="-49" kpx2="38"/><pair kern="-44" kpx2="121"/><pair kern="-54" kpx2="57"/><pair kern="-44" kpx2="126"/><pair kern="-44" kpx2="72"/><pair kern="-40" kpx2="199"/><pair kern="-72" kpx2="180"/><pair kern="-21" kpx2="105"/><pair kern="-49" kpx2="253"/><pair kern="-44" kpx2="125"/><pair kern="-44" kpx2="115"/><pair kern="-17" kpx2="170"/><pair kern="-44" kpx2="88"/><pair kern="-40" kpx2="36"/><pair kern="-44" kpx2="114"/><pair kern="-72" kpx2="55"/><pair kern="-44" kpx2="127"/><pair kern="-21" kpx2="108"/><pair kern="-44" kpx2="128"/><pair kern="-40" kpx2="173"/><pair kern="-21" kpx2="109"/><pair kern="-54" kpx2="92"/><pair kern="-17" kpx2="197"/><pair kern="-21" kpx2="110"/><pair kern="-40" kpx2="174"/></kerning><kerning kpx1="137"><pair kern="-54" kpx2="180"/><pair kern="-40" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-54" kpx2="181"/></kerning><kerning kpx1="233"><pair kern="-44" kpx2="180"/><pair kern="-35" kpx2="197"/><pair kern="-54" kpx2="181"/></kerning><kerning kpx1="253"><pair kern="-17" kpx2="169"/><pair kern="-17" kpx2="60"/><pair kern="-17" kpx2="187"/><pair kern="18" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-17" kpx2="234"/></kerning><kerning kpx1="211"><pair kern="-17" kpx2="229"/><pair kern="-17" kpx2="61"/></kerning><kerning kpx1="78"><pair kern="-17" kpx2="107"/><pair kern="-30" kpx2="126"/><pair kern="-35" kpx2="235"/><pair kern="-35" kpx2="72"/><pair kern="-35" kpx2="112"/><pair kern="-35" kpx2="123"/><pair kern="-35" kpx2="113"/><pair kern="-17" kpx2="105"/><pair kern="-30" kpx2="129"/><pair kern="-35" kpx2="124"/><pair kern="-17" kpx2="106"/><pair kern="-35" kpx2="125"/><pair kern="-35" kpx2="115"/><pair kern="-30" kpx2="88"/><pair kern="-35" kpx2="122"/><pair kern="-17" kpx2="68"/><pair kern="-35" kpx2="82"/><pair kern="-35" kpx2="114"/><pair kern="-35" kpx2="186"/><pair kern="-30" kpx2="127"/><pair kern="-17" kpx2="108"/><pair kern="-30" kpx2="128"/><pair kern="-17" kpx2="109"/><pair kern="-35" kpx2="92"/><pair kern="-35" kpx2="121"/><pair kern="-17" kpx2="110"/></kerning><kerning kpx1="52"><pair kern="-21" kpx2="180"/><pair kern="-63" kpx2="197"/><pair kern="27" kpx2="16"/><pair kern="-17" kpx2="181"/></kerning><kerning kpx1="125"><pair kern="-72" kpx2="180"/><pair kern="-17" kpx2="17"/><pair kern="-63" kpx2="197"/><pair kern="18" kpx2="16"/><pair kern="-30" kpx2="91"/><pair kern="-35" kpx2="181"/></kerning><kerning kpx1="42"><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="169"/><pair kern="-26" kpx2="197"/><pair kern="-35" kpx2="55"/><pair kern="-49" kpx2="60"/><pair kern="-49" kpx2="187"/><pair kern="-21" kpx2="181"/><pair kern="-17" kpx2="170"/><pair kern="-49" kpx2="234"/></kerning><kerning kpx1="170"><pair kern="-17" kpx2="235"/><pair kern="-35" kpx2="199"/><pair kern="-17" kpx2="251"/><pair kern="-109" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-54" kpx2="59"/><pair kern="-109" kpx2="60"/><pair kern="-35" kpx2="201"/><pair kern="-17" kpx2="253"/><pair kern="-109" kpx2="234"/><pair kern="-17" kpx2="90"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="210"/><pair kern="-35" kpx2="36"/><pair kern="-54" kpx2="58"/><pair kern="-91" kpx2="55"/><pair kern="-17" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="50"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="-17" kpx2="39"/><pair kern="-35" kpx2="98"/><pair kern="-17" kpx2="45"/><pair kern="-35" kpx2="173"/><pair kern="-17" kpx2="92"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="89"/><pair kern="-86" kpx2="57"/><pair kern="-35" kpx2="37"/><pair kern="-35" kpx2="174"/></kerning><kerning kpx1="115"><pair kern="-17" kpx2="91"/></kerning><kerning kpx1="90"><pair kern="-91" kpx2="17"/><pair kern="-17" kpx2="169"/><pair kern="-104" kpx2="197"/><pair kern="-54" kpx2="29"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="36"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="55"><pair kern="-165" kpx2="107"/><pair kern="-155" kpx2="235"/><pair kern="-91" kpx2="16"/><pair kern="-169" kpx2="112"/><pair kern="-169" kpx2="123"/><pair kern="-58" kpx2="251"/><pair kern="-169" kpx2="113"/><pair kern="-165" kpx2="86"/><pair kern="-151" kpx2="129"/><pair kern="-169" kpx2="124"/><pair kern="-91" kpx2="169"/><pair kern="-169" kpx2="252"/><pair kern="-169" kpx2="70"/><pair kern="-146" kpx2="85"/><pair kern="-77" kpx2="201"/><pair kern="-165" kpx2="106"/><pair kern="-109" kpx2="29"/><pair kern="-58" kpx2="100"/><pair kern="-169" kpx2="122"/><pair kern="-165" kpx2="68"/><pair kern="-169" kpx2="82"/><pair kern="-155" kpx2="186"/><pair kern="-165" kpx2="250"/><pair kern="-77" kpx2="98"/><pair kern="-21" kpx2="181"/><pair kern="-118" kpx2="17"/><pair kern="-58" kpx2="38"/><pair kern="-169" kpx2="121"/><pair kern="-165" kpx2="228"/><pair kern="-169" kpx2="254"/><pair kern="-151" kpx2="126"/><pair kern="-169" kpx2="72"/><pair kern="-77" kpx2="199"/><pair kern="-165" kpx2="105"/><pair kern="-58" kpx2="253"/><pair kern="-169" kpx2="125"/><pair kern="-169" kpx2="115"/><pair kern="-54" kpx2="170"/><pair kern="-151" kpx2="88"/><pair kern="-169" kpx2="111"/><pair kern="-165" kpx2="90"/><pair kern="-77" kpx2="36"/><pair kern="-17" kpx2="55"/><pair kern="-169" kpx2="114"/><pair kern="-151" kpx2="127"/><pair kern="-165" kpx2="108"/><pair kern="-30" kpx2="76"/><pair kern="-151" kpx2="128"/><pair kern="-77" kpx2="173"/><pair kern="-165" kpx2="109"/><pair kern="-155" kpx2="92"/><pair kern="-128" kpx2="197"/><pair kern="-165" kpx2="110"/><pair kern="-77" kpx2="174"/></kerning><kerning kpx1="114"><pair kern="-17" kpx2="91"/></kerning><kerning kpx1="50"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="27" kpx2="16"/><pair kern="-54" kpx2="187"/><pair kern="-17" kpx2="98"/><pair kern="-17" kpx2="181"/><pair kern="-63" kpx2="59"/><pair kern="-40" kpx2="17"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="29"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="91"><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="111"/><pair kern="-30" kpx2="122"/><pair kern="-30" kpx2="82"/><pair kern="-30" kpx2="114"/><pair kern="-30" kpx2="72"/><pair kern="-30" kpx2="112"/><pair kern="-30" kpx2="123"/><pair kern="-30" kpx2="113"/><pair kern="-30" kpx2="124"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-30" kpx2="121"/><pair kern="-30" kpx2="125"/><pair kern="-30" kpx2="115"/></kerning><kerning kpx1="39"><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="199"/><pair kern="-17" kpx2="98"/><pair kern="-54" kpx2="187"/><pair kern="-26" kpx2="181"/><pair kern="-21" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="169"/><pair kern="-91" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-54" kpx2="60"/><pair kern="-17" kpx2="57"/><pair kern="-17" kpx2="174"/><pair kern="-17" kpx2="170"/><pair kern="-54" kpx2="234"/></kerning><kerning kpx1="236"><pair kern="-17" kpx2="180"/><pair kern="-72" kpx2="17"/><pair kern="-91" kpx2="197"/><pair kern="-35" kpx2="29"/></kerning><kerning kpx1="45"><pair kern="-35" kpx2="180"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="36"/><pair kern="-17" kpx2="169"/><pair kern="-54" kpx2="197"/><pair kern="-17" kpx2="201"/><pair kern="-17" kpx2="199"/><pair kern="-35" kpx2="16"/><pair kern="-17" kpx2="174"/><pair kern="-17" kpx2="98"/><pair kern="-30" kpx2="181"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="173"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="197"><pair kern="-35" kpx2="246"/><pair kern="-54" kpx2="235"/><pair kern="-35" kpx2="43"/><pair kern="-35" kpx2="123"/><pair kern="-54" kpx2="251"/><pair kern="-183" kpx2="187"/><pair kern="-54" kpx2="208"/><pair kern="18" kpx2="144"/><pair kern="-35" kpx2="59"/><pair kern="-17" kpx2="73"/><pair kern="-35" kpx2="41"/><pair kern="-35" kpx2="124"/><pair kern="-35" kpx2="85"/><pair kern="-183" kpx2="60"/><pair kern="18" kpx2="201"/><pair kern="-183" kpx2="234"/><pair kern="-54" kpx2="100"/><pair kern="-35" kpx2="122"/><pair kern="-35" kpx2="47"/><pair kern="-54" kpx2="210"/><pair kern="-35" kpx2="82"/><pair kern="-123" kpx2="58"/><pair kern="-54" kpx2="186"/><pair kern="-54" kpx2="175"/><pair kern="-54" kpx2="209"/><pair kern="-54" kpx2="103"/><pair kern="-35" kpx2="81"/><pair kern="18" kpx2="98"/><pair kern="-54" kpx2="38"/><pair kern="-35" kpx2="121"/><pair kern="-183" kpx2="57"/><pair kern="-35" kpx2="37"/><pair kern="-35" kpx2="120"/><pair kern="-35" kpx2="51"/><pair kern="18" kpx2="199"/><pair kern="-35" kpx2="53"/><pair kern="-35" kpx2="137"/><pair kern="-35" kpx2="233"/><pair kern="-54" kpx2="253"/><pair kern="-54" kpx2="52"/><pair kern="-35" kpx2="125"/><pair kern="-35" kpx2="42"/><pair kern="-95" kpx2="90"/><pair kern="18" kpx2="36"/><pair kern="-137" kpx2="55"/><pair kern="-54" kpx2="50"/><pair kern="-35" kpx2="39"/><pair kern="-35" kpx2="236"/><pair kern="22" kpx2="45"/><pair kern="18" kpx2="173"/><pair kern="-54" kpx2="92"/><pair kern="-114" kpx2="89"/><pair kern="-35" kpx2="46"/><pair kern="18" kpx2="174"/></kerning><kerning kpx1="92"><pair kern="-142" kpx2="17"/><pair kern="-17" kpx2="169"/><pair kern="-146" kpx2="197"/><pair kern="-17" kpx2="16"/><pair kern="-72" kpx2="29"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="89"><pair kern="-77" kpx2="17"/><pair kern="-17" kpx2="169"/><pair kern="-132" kpx2="197"/><pair kern="-26" kpx2="16"/><pair kern="-54" kpx2="29"/><pair kern="-17" kpx2="181"/><pair kern="-17" kpx2="170"/></kerning><kerning kpx1="46"><pair kern="-17" kpx2="107"/><pair kern="-72" kpx2="235"/><pair kern="-104" kpx2="16"/><pair kern="-49" kpx2="112"/><pair kern="-49" kpx2="123"/><pair kern="-54" kpx2="251"/><pair kern="-26" kpx2="213"/><pair kern="-49" kpx2="113"/><pair kern="-35" kpx2="187"/><pair kern="-54" kpx2="208"/><pair kern="-49" kpx2="129"/><pair kern="-49" kpx2="124"/><pair kern="-63" kpx2="169"/><pair kern="-35" kpx2="60"/><pair kern="-17" kpx2="201"/><pair kern="-17" kpx2="106"/><pair kern="-35" kpx2="234"/><pair kern="-54" kpx2="100"/><pair kern="-49" kpx2="122"/><pair kern="-17" kpx2="68"/><pair kern="-54" kpx2="210"/><pair kern="-35" kpx2="58"/><pair kern="-49" kpx2="82"/><pair kern="-72" kpx2="186"/><pair kern="-54" kpx2="175"/><pair kern="-54" kpx2="209"/><pair kern="-54" kpx2="103"/><pair kern="-17" kpx2="98"/><pair kern="-30" kpx2="181"/><pair kern="-26" kpx2="212"/><pair kern="-54" kpx2="38"/><pair kern="-49" kpx2="121"/><pair kern="-49" kpx2="126"/><pair kern="-26" kpx2="104"/><pair kern="-49" kpx2="72"/><pair kern="-17" kpx2="199"/><pair kern="-30" kpx2="180"/><pair kern="-17" kpx2="105"/><pair kern="-54" kpx2="253"/><pair kern="-26" kpx2="211"/><pair kern="-49" kpx2="125"/><pair kern="-49" kpx2="115"/><pair kern="-49" kpx2="88"/><pair kern="-17" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-49" kpx2="114"/><pair kern="-54" kpx2="50"/><pair kern="-49" kpx2="127"/><pair kern="-17" kpx2="108"/><pair kern="-49" kpx2="128"/><pair kern="-17" kpx2="173"/><pair kern="-17" kpx2="109"/><pair kern="-72" kpx2="92"/><pair kern="-17" kpx2="110"/><pair kern="-17" kpx2="174"/><pair kern="-26" kpx2="56"/></kerning><kerning kpx1="174"><pair kern="-17" kpx2="246"/><pair kern="-67" kpx2="235"/><pair kern="-21" kpx2="16"/><pair kern="-17" kpx2="112"/><pair kern="-17" kpx2="123"/><pair kern="-17" kpx2="251"/><pair kern="-17" kpx2="113"/><pair kern="-77" kpx2="187"/><pair kern="-17" kpx2="208"/><pair kern="-35" kpx2="73"/><pair kern="-17" kpx2="124"/><pair kern="-35" kpx2="169"/><pair kern="-17" kpx2="252"/><pair kern="-17" kpx2="70"/><pair kern="-77" kpx2="60"/><pair kern="27" kpx2="201"/><pair kern="-17" kpx2="29"/><pair kern="-77" kpx2="234"/><pair kern="-17" kpx2="100"/><pair kern="-17" kpx2="122"/><pair kern="-17" kpx2="210"/><pair kern="-17" kpx2="82"/><pair kern="-54" kpx2="58"/><pair kern="-67" kpx2="186"/><pair kern="-17" kpx2="175"/><pair kern="-17" kpx2="209"/><pair kern="-17" kpx2="103"/><pair kern="27" kpx2="98"/><pair kern="-123" kpx2="181"/><pair kern="-17" kpx2="17"/><pair kern="-17" kpx2="38"/><pair kern="-17" kpx2="84"/><pair kern="-17" kpx2="121"/><pair kern="-63" kpx2="57"/><pair kern="-17" kpx2="254"/><pair kern="-17" kpx2="87"/><pair kern="-17" kpx2="72"/><pair kern="27" kpx2="199"/><pair kern="-17" kpx2="71"/><pair kern="-128" kpx2="180"/><pair kern="-17" kpx2="253"/><pair kern="-17" kpx2="52"/><pair kern="-17" kpx2="125"/><pair kern="-17" kpx2="42"/><pair kern="-17" kpx2="115"/><pair kern="-40" kpx2="90"/><pair kern="-17" kpx2="111"/><pair kern="27" kpx2="36"/><pair kern="-77" kpx2="55"/><pair kern="-17" kpx2="114"/><pair kern="-17" kpx2="50"/><pair kern="27" kpx2="173"/><pair kern="-67" kpx2="92"/><pair kern="22" kpx2="197"/><pair kern="-58" kpx2="89"/><pair kern="27" kpx2="174"/></kerning><kerning kpx1="56"><pair kern="-17" kpx2="229"/><pair kern="-17" kpx2="61"/></kerning></font-metrics>
\ No newline at end of file
diff --git a/bitbake/doc/template/VeraMoBd.xml b/bitbake/doc/template/VeraMoBd.xml
deleted file mode 100644
index 9b33107a..00000000
--- a/bitbake/doc/template/VeraMoBd.xml
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><font-metrics metrics-version="2" type="TYPE0"><font-name>BitstreamVeraSansMono-Bold</font-name><full-name>Bitstream Vera Sans Mono Bold</full-name><family-name>Bitstream Vera Sans Mono</family-name><embed/><cap-height>729</cap-height><x-height>546</x-height><ascender>759</ascender><descender>-240</descender><bbox><left>-19</left><bottom>-235</bottom><right>605</right><top>928</top></bbox><flags>34</flags><stemv>0</stemv><italicangle>0</italicangle><subtype>TYPE0</subtype><multibyte-extras><cid-type>CIDFontType2</cid-type><default-width>0</default-width><bfranges><bf gi="3" ue="126" us="32"/><bf gi="172" ue="160" us="160"/><bf gi="163" ue="161" us="161"/><bf gi="132" ue="163" us="162"/><bf gi="189" ue="164" us="164"/><bf gi="150" ue="165" us="165"/><bf gi="231" ue="166" us="166"/><bf gi="134" ue="167" us="167"/><bf gi="142" ue="168" us="168"/><bf gi="139" ue="169" us="169"/><bf gi="157" ue="170" us="170"/><bf gi="169" ue="171" us="171"/><bf gi="164" ue="172" us="172"/><bf gi="256" ue="173" us="173"/><bf gi="138" ue="174" us="174"/><bf gi="217" ue="175" us="175"/><bf gi="131" ue="176" us="176"/><bf gi="147" ue="177" us="177"/><bf gi="241" ue="179" us="178"/><bf gi="141" ue="180" us="180"/><bf gi="151" ue="181" us="181"/><bf gi="136" ue="182" us="182"/><bf gi="195" ue="183" us="183"/><bf gi="221" ue="184" us="184"/><bf gi="240" ue="185" us="185"/><bf gi="158" ue="186" us="186"/><bf gi="170" ue="187" us="187"/><bf gi="243" ue="190" us="188"/><bf gi="162" ue="191" us="191"/><bf gi="173" ue="192" us="192"/><bf gi="201" ue="193" us="193"/><bf gi="199" ue="194" us="194"/><bf gi="174" ue="195" us="195"/><bf gi="98" ue="197" us="196"/><bf gi="144" ue="198" us="198"/><bf gi="100" ue="199" us="199"/><bf gi="203" ue="200" us="200"/><bf gi="101" ue="201" us="201"/><bf gi="200" ue="202" us="202"/><bf gi="202" ue="203" us="203"/><bf gi="207" ue="204" us="204"/><bf gi="204" ue="207" us="205"/><bf gi="232" ue="208" us="208"/><bf gi="102" ue="209" us="209"/><bf gi="210" ue="210" us="210"/><bf gi="208" ue="212" us="211"/><bf gi="175" ue="213" us="213"/><bf gi="103" ue="214" us="214"/><bf gi="239" ue="215" us="215"/><bf gi="145" ue="216" us="216"/><bf gi="213" ue="217" us="217"/><bf gi="211" ue="219" us="218"/><bf gi="104" ue="220" us="220"/><bf gi="234" ue="221" us="221"/><bf gi="236" ue="222" us="222"/><bf gi="137" ue="223" us="223"/><bf gi="106" ue="224" us="224"/><bf gi="105" ue="225" us="225"/><bf gi="107" ue="226" us="226"/><bf gi="109" ue="227" us="227"/><bf gi="108" ue="228" us="228"/><bf gi="110" ue="229" us="229"/><bf gi="160" ue="230" us="230"/><bf gi="111" ue="231" us="231"/><bf gi="113" ue="232" us="232"/><bf gi="112" ue="233" us="233"/><bf gi="114" ue="235" us="234"/><bf gi="117" ue="236" us="236"/><bf gi="116" ue="237" us="237"/><bf gi="118" ue="239" us="238"/><bf gi="233" ue="240" us="240"/><bf gi="120" ue="241" us="241"/><bf gi="122" ue="242" us="242"/><bf gi="121" ue="243" us="243"/><bf gi="123" ue="244" us="244"/><bf gi="125" ue="245" us="245"/><bf gi="124" ue="246" us="246"/><bf gi="184" ue="247" us="247"/><bf gi="161" ue="248" us="248"/><bf gi="127" ue="249" us="249"/><bf gi="126" ue="250" us="250"/><bf gi="128" ue="252" us="251"/><bf gi="235" ue="253" us="253"/><bf gi="237" ue="254" us="254"/><bf gi="186" ue="255" us="255"/><bf gi="251" ue="263" us="262"/><bf gi="253" ue="269" us="268"/><bf gi="0" ue="270" us="270"/><bf gi="0" ue="271" us="271"/><bf gi="0" ue="272" us="272"/><bf gi="255" ue="273" us="273"/><bf gi="246" ue="287" us="286"/><bf gi="248" ue="304" us="304"/><bf gi="214" ue="305" us="305"/><bf gi="225" ue="322" us="321"/><bf gi="176" ue="339" us="338"/><bf gi="249" ue="351" us="350"/><bf gi="227" ue="353" us="352"/><bf gi="187" ue="376" us="376"/><bf gi="229" ue="382" us="381"/><bf gi="166" ue="402" us="402"/><bf gi="215" ue="710" us="710"/><bf gi="224" ue="711" us="711"/><bf gi="218" ue="730" us="728"/><bf gi="223" ue="731" us="731"/><bf gi="216" ue="732" us="732"/><bf gi="222" ue="733" us="733"/><bf gi="159" ue="937" us="937"/><bf gi="155" ue="960" us="960"/><bf gi="178" ue="8212" us="8211"/><bf gi="0" ue="8213" us="8213"/><bf gi="0" ue="8214" us="8214"/><bf gi="0" ue="8215" us="8215"/><bf gi="182" ue="8217" us="8216"/><bf gi="196" ue="8218" us="8218"/><bf gi="0" ue="8219" us="8219"/><bf gi="180" ue="8221" us="8220"/><bf gi="197" ue="8222" us="8222"/><bf gi="0" ue="8223" us="8223"/><bf gi="130" ue="8224" us="8224"/><bf gi="194" ue="8225" us="8225"/><bf gi="135" ue="8226" us="8226"/><bf gi="0" ue="8227" us="8227"/><bf gi="0" ue="8228" us="8228"/><bf gi="0" ue="8229" us="8229"/><bf gi="171" ue="8230" us="8230"/><bf gi="198" ue="8240" us="8240"/><bf gi="190" ue="8250" us="8249"/><bf gi="258" ue="8364" us="8364"/><bf gi="140" ue="8482" us="8482"/><bf gi="152" ue="8706" us="8706"/><bf gi="0" ue="8707" us="8707"/><bf gi="0" ue="8708" us="8708"/><bf gi="0" ue="8709" us="8709"/><bf gi="168" ue="8710" us="8710"/><bf gi="154" ue="8719" us="8719"/><bf gi="0" ue="8720" us="8720"/><bf gi="153" ue="8721" us="8721"/><bf gi="238" ue="8722" us="8722"/><bf gi="0" ue="8723" us="8723"/><bf gi="0" ue="8724" us="8724"/><bf gi="188" ue="8725" us="8725"/><bf gi="0" ue="8726" us="8726"/><bf gi="0" ue="8727" us="8727"/><bf gi="0" ue="8728" us="8728"/><bf gi="257" ue="8729" us="8729"/><bf gi="165" ue="8730" us="8730"/><bf gi="0" ue="8731" us="8731"/><bf gi="0" ue="8732" us="8732"/><bf gi="0" ue="8733" us="8733"/><bf gi="146" ue="8734" us="8734"/><bf gi="156" ue="8747" us="8747"/><bf gi="167" ue="8776" us="8776"/><bf gi="143" ue="8800" us="8800"/><bf gi="0" ue="8801" us="8801"/><bf gi="0" ue="8802" us="8802"/><bf gi="0" ue="8803" us="8803"/><bf gi="148" ue="8805" us="8804"/><bf gi="185" ue="9674" us="9674"/><bf gi="192" ue="64258" us="64257"/><bf gi="0" ue="65535" us="65535"/></bfranges><cid-widths start-index="0"><wx w="602"/><wx w="0"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/></cid-widths></multibyte-extras></font-metrics>
\ No newline at end of file
diff --git a/bitbake/doc/template/VeraMono.xml b/bitbake/doc/template/VeraMono.xml
deleted file mode 100644
index 3a0a8665..00000000
--- a/bitbake/doc/template/VeraMono.xml
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><font-metrics metrics-version="2" type="TYPE0"><font-name>BitstreamVeraSansMono-Roman</font-name><full-name>Bitstream Vera Sans Mono</full-name><family-name>Bitstream Vera Sans Mono</family-name><embed/><cap-height>729</cap-height><x-height>546</x-height><ascender>759</ascender><descender>-240</descender><bbox><left>-4</left><bottom>-235</bottom><right>605</right><top>928</top></bbox><flags>34</flags><stemv>0</stemv><italicangle>0</italicangle><subtype>TYPE0</subtype><multibyte-extras><cid-type>CIDFontType2</cid-type><default-width>0</default-width><bfranges><bf gi="3" ue="126" us="32"/><bf gi="172" ue="160" us="160"/><bf gi="163" ue="161" us="161"/><bf gi="132" ue="163" us="162"/><bf gi="189" ue="164" us="164"/><bf gi="150" ue="165" us="165"/><bf gi="231" ue="166" us="166"/><bf gi="134" ue="167" us="167"/><bf gi="142" ue="168" us="168"/><bf gi="139" ue="169" us="169"/><bf gi="157" ue="170" us="170"/><bf gi="169" ue="171" us="171"/><bf gi="164" ue="172" us="172"/><bf gi="256" ue="173" us="173"/><bf gi="138" ue="174" us="174"/><bf gi="217" ue="175" us="175"/><bf gi="131" ue="176" us="176"/><bf gi="147" ue="177" us="177"/><bf gi="241" ue="179" us="178"/><bf gi="141" ue="180" us="180"/><bf gi="151" ue="181" us="181"/><bf gi="136" ue="182" us="182"/><bf gi="195" ue="183" us="183"/><bf gi="221" ue="184" us="184"/><bf gi="240" ue="185" us="185"/><bf gi="158" ue="186" us="186"/><bf gi="170" ue="187" us="187"/><bf gi="243" ue="190" us="188"/><bf gi="162" ue="191" us="191"/><bf gi="173" ue="192" us="192"/><bf gi="201" ue="193" us="193"/><bf gi="199" ue="194" us="194"/><bf gi="174" ue="195" us="195"/><bf gi="98" ue="197" us="196"/><bf gi="144" ue="198" us="198"/><bf gi="100" ue="199" us="199"/><bf gi="203" ue="200" us="200"/><bf gi="101" ue="201" us="201"/><bf gi="200" ue="202" us="202"/><bf gi="202" ue="203" us="203"/><bf gi="207" ue="204" us="204"/><bf gi="204" ue="207" us="205"/><bf gi="232" ue="208" us="208"/><bf gi="102" ue="209" us="209"/><bf gi="210" ue="210" us="210"/><bf gi="208" ue="212" us="211"/><bf gi="175" ue="213" us="213"/><bf gi="103" ue="214" us="214"/><bf gi="239" ue="215" us="215"/><bf gi="145" ue="216" us="216"/><bf gi="213" ue="217" us="217"/><bf gi="211" ue="219" us="218"/><bf gi="104" ue="220" us="220"/><bf gi="234" ue="221" us="221"/><bf gi="236" ue="222" us="222"/><bf gi="137" ue="223" us="223"/><bf gi="106" ue="224" us="224"/><bf gi="105" ue="225" us="225"/><bf gi="107" ue="226" us="226"/><bf gi="109" ue="227" us="227"/><bf gi="108" ue="228" us="228"/><bf gi="110" ue="229" us="229"/><bf gi="160" ue="230" us="230"/><bf gi="111" ue="231" us="231"/><bf gi="113" ue="232" us="232"/><bf gi="112" ue="233" us="233"/><bf gi="114" ue="235" us="234"/><bf gi="117" ue="236" us="236"/><bf gi="116" ue="237" us="237"/><bf gi="118" ue="239" us="238"/><bf gi="233" ue="240" us="240"/><bf gi="120" ue="241" us="241"/><bf gi="122" ue="242" us="242"/><bf gi="121" ue="243" us="243"/><bf gi="123" ue="244" us="244"/><bf gi="125" ue="245" us="245"/><bf gi="124" ue="246" us="246"/><bf gi="184" ue="247" us="247"/><bf gi="161" ue="248" us="248"/><bf gi="127" ue="249" us="249"/><bf gi="126" ue="250" us="250"/><bf gi="128" ue="252" us="251"/><bf gi="235" ue="253" us="253"/><bf gi="237" ue="254" us="254"/><bf gi="186" ue="255" us="255"/><bf gi="251" ue="263" us="262"/><bf gi="253" ue="269" us="268"/><bf gi="0" ue="270" us="270"/><bf gi="0" ue="271" us="271"/><bf gi="0" ue="272" us="272"/><bf gi="255" ue="273" us="273"/><bf gi="246" ue="287" us="286"/><bf gi="248" ue="304" us="304"/><bf gi="214" ue="305" us="305"/><bf gi="225" ue="322" us="321"/><bf gi="176" ue="339" us="338"/><bf gi="249" ue="351" us="350"/><bf gi="227" ue="353" us="352"/><bf gi="187" ue="376" us="376"/><bf gi="229" ue="382" us="381"/><bf gi="166" ue="402" us="402"/><bf gi="215" ue="710" us="710"/><bf gi="224" ue="711" us="711"/><bf gi="218" ue="730" us="728"/><bf gi="223" ue="731" us="731"/><bf gi="216" ue="732" us="732"/><bf gi="222" ue="733" us="733"/><bf gi="159" ue="937" us="937"/><bf gi="155" ue="960" us="960"/><bf gi="178" ue="8212" us="8211"/><bf gi="0" ue="8213" us="8213"/><bf gi="0" ue="8214" us="8214"/><bf gi="0" ue="8215" us="8215"/><bf gi="182" ue="8217" us="8216"/><bf gi="196" ue="8218" us="8218"/><bf gi="0" ue="8219" us="8219"/><bf gi="180" ue="8221" us="8220"/><bf gi="197" ue="8222" us="8222"/><bf gi="0" ue="8223" us="8223"/><bf gi="130" ue="8224" us="8224"/><bf gi="194" ue="8225" us="8225"/><bf gi="135" ue="8226" us="8226"/><bf gi="0" ue="8227" us="8227"/><bf gi="0" ue="8228" us="8228"/><bf gi="0" ue="8229" us="8229"/><bf gi="171" ue="8230" us="8230"/><bf gi="198" ue="8240" us="8240"/><bf gi="190" ue="8250" us="8249"/><bf gi="258" ue="8364" us="8364"/><bf gi="140" ue="8482" us="8482"/><bf gi="152" ue="8706" us="8706"/><bf gi="0" ue="8707" us="8707"/><bf gi="0" ue="8708" us="8708"/><bf gi="0" ue="8709" us="8709"/><bf gi="168" ue="8710" us="8710"/><bf gi="154" ue="8719" us="8719"/><bf gi="0" ue="8720" us="8720"/><bf gi="153" ue="8721" us="8721"/><bf gi="238" ue="8722" us="8722"/><bf gi="0" ue="8723" us="8723"/><bf gi="0" ue="8724" us="8724"/><bf gi="188" ue="8725" us="8725"/><bf gi="0" ue="8726" us="8726"/><bf gi="0" ue="8727" us="8727"/><bf gi="0" ue="8728" us="8728"/><bf gi="257" ue="8729" us="8729"/><bf gi="165" ue="8730" us="8730"/><bf gi="0" ue="8731" us="8731"/><bf gi="0" ue="8732" us="8732"/><bf gi="0" ue="8733" us="8733"/><bf gi="146" ue="8734" us="8734"/><bf gi="156" ue="8747" us="8747"/><bf gi="167" ue="8776" us="8776"/><bf gi="143" ue="8800" us="8800"/><bf gi="0" ue="8801" us="8801"/><bf gi="0" ue="8802" us="8802"/><bf gi="0" ue="8803" us="8803"/><bf gi="148" ue="8805" us="8804"/><bf gi="185" ue="9674" us="9674"/><bf gi="192" ue="64258" us="64257"/><bf gi="0" ue="65535" us="65535"/></bfranges><cid-widths start-index="0"><wx w="602"/><wx w="0"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/><wx w="602"/></cid-widths></multibyte-extras></font-metrics>
\ No newline at end of file
diff --git a/bitbake/doc/template/component.title.xsl b/bitbake/doc/template/component.title.xsl
deleted file mode 100644
index faef0432..00000000
--- a/bitbake/doc/template/component.title.xsl
+++ /dev/null
@@ -1,39 +0,0 @@
-<xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:d="http://docbook.org/ns/docbook"
-  xmlns="http://www.w3.org/1999/xhtml"
-  exclude-result-prefixes="d">
-  
-  <xsl:template name="component.title">
-    <xsl:param name="node" select="."/>
-    
-    <xsl:variable name="level">
-      <xsl:choose>
-        <xsl:when test="ancestor::d:section">
-          <xsl:value-of select="count(ancestor::d:section)+1"/>
-        </xsl:when>
-        <xsl:when test="ancestor::d:sect5">6</xsl:when>
-        <xsl:when test="ancestor::d:sect4">5</xsl:when>
-        <xsl:when test="ancestor::d:sect3">4</xsl:when>
-        <xsl:when test="ancestor::d:sect2">3</xsl:when>
-        <xsl:when test="ancestor::d:sect1">2</xsl:when>
-        <xsl:otherwise>1</xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:element name="h{$level+1}" namespace="http://www.w3.org/1999/xhtml">
-      <xsl:attribute name="class">title</xsl:attribute>
-      <xsl:if test="$generate.id.attributes = 0">
-        <xsl:call-template name="anchor">
-          <xsl:with-param name="node" select="$node"/>
-          <xsl:with-param name="conditional" select="0"/>
-        </xsl:call-template>
-      </xsl:if>
-      <xsl:apply-templates select="$node" mode="object.title.markup">
-        <xsl:with-param name="allow-anchors" select="1"/>
-      </xsl:apply-templates>
-      <xsl:call-template name="permalink">
-        <xsl:with-param name="node" select="$node"/>
-      </xsl:call-template>
-    </xsl:element>
-  </xsl:template>
-</xsl:stylesheet>
diff --git a/bitbake/doc/template/db-pdf.xsl b/bitbake/doc/template/db-pdf.xsl
deleted file mode 100644
index 3dd065a5..00000000
--- a/bitbake/doc/template/db-pdf.xsl
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version='1.0'?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
-  
-  <xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl" />
-
-  <!-- check project-plan.sh for how this is generated, needed to tweak 
-       the cover page     
-    -->
-  <xsl:include href="/tmp/titlepage.xsl"/> 
-
-  <!-- To force a page break in document, i.e per section add a 
-      <?hard-pagebreak?> tag.
-  -->
- <xsl:template match="processing-instruction('hard-pagebreak')">
-   <fo:block break-before='page' />
- </xsl:template>
-
-  <!--Fix for defualt indent getting TOC all wierd..
-      See http://sources.redhat.com/ml/docbook-apps/2005-q1/msg00455.html 
-      FIXME: must be a better fix
-    -->
-  <xsl:param name="body.start.indent" select="'0'"/>
-  <!--<xsl:param name="title.margin.left" select="'0'"/>-->
-
-  <!-- stop long-ish header titles getting wrapped -->
-  <xsl:param name="header.column.widths">1 10 1</xsl:param>
-
-  <!-- customise headers and footers a little --> 
-
-  <xsl:template name="head.sep.rule">
-   <xsl:if test="$header.rule != 0">
-     <xsl:attribute name="border-bottom-width">0.5pt</xsl:attribute>
-     <xsl:attribute name="border-bottom-style">solid</xsl:attribute>
-     <xsl:attribute name="border-bottom-color">#cccccc</xsl:attribute>
-   </xsl:if>
-  </xsl:template>
-
-  <xsl:template name="foot.sep.rule">
-    <xsl:if test="$footer.rule != 0">
-     <xsl:attribute name="border-top-width">0.5pt</xsl:attribute>
-     <xsl:attribute name="border-top-style">solid</xsl:attribute>
-     <xsl:attribute name="border-top-color">#cccccc</xsl:attribute>
-    </xsl:if>
-  </xsl:template>
-
-  <xsl:attribute-set name="header.content.properties">
-    <xsl:attribute name="color">#cccccc</xsl:attribute>
-  </xsl:attribute-set>
-
-  <xsl:attribute-set name="footer.content.properties">
-    <xsl:attribute name="color">#cccccc</xsl:attribute>
-  </xsl:attribute-set>
-
- 
-  <!-- general settings -->
-
-  <xsl:param name="fop1.extensions" select="1"></xsl:param>
-  <xsl:param name="paper.type" select="'A4'"></xsl:param>
-  <xsl:param name="section.autolabel" select="1"></xsl:param>
-  <xsl:param name="body.font.family" select="'verasans'"></xsl:param>
-  <xsl:param name="title.font.family" select="'verasans'"></xsl:param>
-  <xsl:param name="monospace.font.family" select="'veramono'"></xsl:param>
-
-</xsl:stylesheet>
diff --git a/bitbake/doc/template/division.title.xsl b/bitbake/doc/template/division.title.xsl
deleted file mode 100644
index 9c843bc7..00000000
--- a/bitbake/doc/template/division.title.xsl
+++ /dev/null
@@ -1,25 +0,0 @@
-<xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:d="http://docbook.org/ns/docbook"
-  xmlns="http://www.w3.org/1999/xhtml"
-  exclude-result-prefixes="d">
-  
-  <xsl:template name="division.title">
-    <xsl:param name="node" select="."/>
-    
-    <h1>
-      <xsl:attribute name="class">title</xsl:attribute>
-      <xsl:call-template name="anchor">
-        <xsl:with-param name="node" select="$node"/>
-        <xsl:with-param name="conditional" select="0"/>
-      </xsl:call-template>
-      <xsl:apply-templates select="$node" mode="object.title.markup">
-        <xsl:with-param name="allow-anchors" select="1"/>
-      </xsl:apply-templates>
-      <xsl:call-template name="permalink">
-        <xsl:with-param name="node" select="$node"/>
-      </xsl:call-template>
-    </h1>
-  </xsl:template>
-</xsl:stylesheet>
-
diff --git a/bitbake/doc/template/fop-config.xml b/bitbake/doc/template/fop-config.xml
deleted file mode 100644
index 09cc5ca0..00000000
--- a/bitbake/doc/template/fop-config.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<fop version="1.0">
-
-  <!-- Strict user configuration -->
-  <strict-configuration>true</strict-configuration>
-
-  <!-- Strict FO validation -->
-  <strict-validation>true</strict-validation>
-
-   <!--
-    Set the baseDir so common/openedhand.svg references in plans still
-    work ok. Note, relative file references to current dir should still work.
-    -->	
-  <base>../template</base>
-  <font-base>../template</font-base>
- 
-  <!-- Source resolution in dpi (dots/pixels per inch) for determining the
-       size of pixels in SVG and bitmap images, default: 72dpi -->
-  <!-- <source-resolution>72</source-resolution> -->
-  <!-- Target resolution in dpi (dots/pixels per inch) for specifying the
-       target resolution for generated bitmaps, default: 72dpi -->
-  <!-- <target-resolution>72</target-resolution> -->
- 
-  <!-- default page-height and page-width, in case
-       value is specified as auto -->
-  <default-page-settings height="11in" width="8.26in"/> 
- 
-  <!-- <use-cache>false</use-cache> -->
- 
-  <renderers>
-    <renderer mime="application/pdf">
-      <fonts>
-        <font  metrics-file="VeraMono.xml"
-               kerning="yes" 
-               embed-url="VeraMono.ttf">
-          <font-triplet name="veramono" style="normal" weight="normal"/>
-        </font>
-
-        <font  metrics-file="VeraMoBd.xml"
-               kerning="yes" 
-               embed-url="VeraMoBd.ttf">
-          <font-triplet name="veramono" style="normal" weight="bold"/>
-        </font>
-
-        <font  metrics-file="Vera.xml"
-               kerning="yes" 
-               embed-url="Vera.ttf">
-          <font-triplet name="verasans" style="normal" weight="normal"/>
-          <font-triplet name="verasans" style="normal" weight="bold"/>
-          <font-triplet name="verasans" style="italic" weight="normal"/>
-          <font-triplet name="verasans" style="italic" weight="bold"/>
-        </font>
-        
-        <auto-detect/>
-      </fonts>
-    </renderer>
-  </renderers>
-</fop>
-
diff --git a/bitbake/doc/template/formal.object.heading.xsl b/bitbake/doc/template/formal.object.heading.xsl
deleted file mode 100644
index 4f3900d1..00000000
--- a/bitbake/doc/template/formal.object.heading.xsl
+++ /dev/null
@@ -1,21 +0,0 @@
-<xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:d="http://docbook.org/ns/docbook"
-  xmlns="http://www.w3.org/1999/xhtml"
-  exclude-result-prefixes="d">
-  
-  <xsl:template name="formal.object.heading">
-    <xsl:param name="object" select="."/>
-    <xsl:param name="title">
-      <xsl:apply-templates select="$object" mode="object.title.markup">
-        <xsl:with-param name="allow-anchors" select="1"/>
-      </xsl:apply-templates>
-    </xsl:param>
-    <p class="title">
-      <b><xsl:copy-of select="$title"/></b>
-      <xsl:call-template name="permalink">
-        <xsl:with-param name="node" select="$object"/>
-      </xsl:call-template>
-    </p>
-  </xsl:template>
-</xsl:stylesheet>
\ No newline at end of file
diff --git a/bitbake/doc/template/gloss-permalinks.xsl b/bitbake/doc/template/gloss-permalinks.xsl
deleted file mode 100644
index 6bf58116..00000000
--- a/bitbake/doc/template/gloss-permalinks.xsl
+++ /dev/null
@@ -1,14 +0,0 @@
-<xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:d="http://docbook.org/ns/docbook"
-  xmlns="http://www.w3.org/1999/xhtml">
-
-  <xsl:template match="glossentry/glossterm">
-    <xsl:apply-imports/>
-    <xsl:if test="$generate.permalink != 0">
-      <xsl:call-template name="permalink">
-        <xsl:with-param name="node" select=".."/>
-      </xsl:call-template>
-    </xsl:if>
-  </xsl:template>
-</xsl:stylesheet>
diff --git a/bitbake/doc/template/permalinks.xsl b/bitbake/doc/template/permalinks.xsl
deleted file mode 100644
index d2a1c145..00000000
--- a/bitbake/doc/template/permalinks.xsl
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet version="1.0"
-  xmlns="http://www.w3.org/1999/xhtml"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-  <xsl:param name="generate.permalink" select="1"/>
-  <xsl:param name="permalink.text">¶</xsl:param>
-
-  <xsl:template name="permalink">
-    <xsl:param name="node"/>
-
-    <xsl:if test="$generate.permalink != '0'">
-      <span class="permalink">
-        <a alt="Permalink" title="Permalink">
-          <xsl:attribute name="href">
-            <xsl:call-template name="href.target">
-              <xsl:with-param name="object"  select="$node"/>
-            </xsl:call-template>
-          </xsl:attribute>
-          <xsl:copy-of select="$permalink.text"/>
-        </a>
-      </span>
-    </xsl:if>
-  </xsl:template>
-</xsl:stylesheet>
diff --git a/bitbake/doc/template/section.title.xsl b/bitbake/doc/template/section.title.xsl
deleted file mode 100644
index 5c6ff9a9..00000000
--- a/bitbake/doc/template/section.title.xsl
+++ /dev/null
@@ -1,55 +0,0 @@
-<xsl:stylesheet version="1.0"
-  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-  xmlns:d="http://docbook.org/ns/docbook"
-  xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="d">
-
-  <xsl:template name="section.title">
-    <xsl:variable name="section"
-      select="(ancestor::section |
-               ancestor::simplesect|
-               ancestor::sect1|
-               ancestor::sect2|
-               ancestor::sect3|
-               ancestor::sect4|
-               ancestor::sect5)[last()]"/>
-
-    <xsl:variable name="renderas">
-      <xsl:choose>
-        <xsl:when test="$section/@renderas = 'sect1'">1</xsl:when>
-        <xsl:when test="$section/@renderas = 'sect2'">2</xsl:when>
-        <xsl:when test="$section/@renderas = 'sect3'">3</xsl:when>
-        <xsl:when test="$section/@renderas = 'sect4'">4</xsl:when>
-        <xsl:when test="$section/@renderas = 'sect5'">5</xsl:when>
-        <xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-
-    <xsl:variable name="level">
-      <xsl:choose>
-        <xsl:when test="$renderas != ''">
-          <xsl:value-of select="$renderas"/>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:call-template name="section.level">
-            <xsl:with-param name="node" select="$section"/>
-          </xsl:call-template>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-
-    <xsl:call-template name="section.heading">
-      <xsl:with-param name="section" select="$section"/>
-      <xsl:with-param name="level" select="$level"/>
-      <xsl:with-param name="title">
-        <xsl:apply-templates select="$section" mode="object.title.markup">
-          <xsl:with-param name="allow-anchors" select="1"/>
-        </xsl:apply-templates>
-        <xsl:if test="$level &gt; 0">
-          <xsl:call-template name="permalink">
-            <xsl:with-param name="node" select="$section"/>
-          </xsl:call-template>
-        </xsl:if>
-      </xsl:with-param>
-    </xsl:call-template>
-  </xsl:template>
-</xsl:stylesheet>
diff --git a/bitbake/doc/template/titlepage.templates.xml b/bitbake/doc/template/titlepage.templates.xml
deleted file mode 100644
index 38ec11a4..00000000
--- a/bitbake/doc/template/titlepage.templates.xml
+++ /dev/null
@@ -1,1259 +0,0 @@
-<!DOCTYPE t:templates [
-<!ENTITY hsize0 "10pt">
-<!ENTITY hsize1 "12pt">
-<!ENTITY hsize2 "14.4pt">
-<!ENTITY hsize3 "17.28pt">
-<!ENTITY hsize4 "20.736pt">
-<!ENTITY hsize5 "24.8832pt">
-<!ENTITY hsize0space "7.5pt"> <!-- 0.75 * hsize0 -->
-<!ENTITY hsize1space "9pt"> <!-- 0.75 * hsize1 -->
-<!ENTITY hsize2space "10.8pt"> <!-- 0.75 * hsize2 -->
-<!ENTITY hsize3space "12.96pt"> <!-- 0.75 * hsize3 -->
-<!ENTITY hsize4space "15.552pt"> <!-- 0.75 * hsize4 -->
-<!ENTITY hsize5space "18.6624pt"> <!-- 0.75 * hsize5 -->
-]>
-<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0"
-	     xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param"
-             xmlns:fo="http://www.w3.org/1999/XSL/Format"
-             xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-
-<!-- ********************************************************************
-     $Id: titlepage.templates.xml,v 1.23 2003/12/16 00:30:49 bobstayton Exp $
-     ********************************************************************
-
-     This file is part of the DocBook XSL Stylesheet distribution.
-     See ../README or http://docbook.sf.net/ for copyright
-     and other information.
-
-     ******************************************************************** -->
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="article" t:wrapper="fo:block"
-             font-family="{$title.fontset}">
-
-  <t:titlepage-content t:side="recto"
-             text-align="center">
-
-    <mediaobject/>
-
-    <title t:named-template="component.title"
-	   param:node="ancestor-or-self::article[1]"
-	   keep-with-next="always"
-	   font-size="&hsize5;"
-	   font-weight="bold"/>
-
-    <subtitle param:node="ancestor-or-self::article[1]"
-	   keep-with-next="always"
-	   font-size="&hsize3;"
-	   font-weight="bold"
-       space-after="0.8em"/>
-
-    <corpauthor space-before="0.5em"
-                font-size="&hsize3;"/>
-    <authorgroup space-before="0.5em"
-                 font-size="&hsize2;"/>
-    <author space-before="0.5em"
-            font-size="&hsize2;"
-            space-after="0.8em"/>
-
-    <email font-size="&hsize2;"/>
-
-    <othercredit space-before="0.5em"/>
-    <releaseinfo space-before="0.5em"/>
-    <copyright space-before="0.5em"/>
-    <legalnotice text-align="start"
-                 margin-left="0.5in"
-                 margin-right="0.5in"
-                 font-family="{$body.fontset}"/>
-    <pubdate space-before="0.5em"/>
-	<para></para>
-    <revision space-before="0.5em"/>
-    <revhistory space-before="0.5em"/>
-    <abstract space-before="0.5em"
-	      text-align="start"
-	      margin-left="0.5in"
-              margin-right="0.5in"
-              font-family="{$body.fontset}"/>
-
-    <para></para>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="set" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-      <title
-	     t:named-template="division.title"
-	     param:node="ancestor-or-self::set[1]"
-	     text-align="center"
-	     font-size="&hsize5;"
-	     space-before="&hsize5space;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"
-	      text-align="center"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="book" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-
-      <mediaobject/>
-
-<!--
-
-# If you leave this block of code in then the text title in the
-# <title>BitBake User Manual</title> statement of the
-# bitbake-user-manual.xml file is rendered on the title page below the
-# image.  Commenting it out gets it out of there yet allows it
-# to be retained in the tab text for the HTML version of the
-# manual.
-
-      <title
-	     t:named-template="division.title"
-	     param:node="ancestor-or-self::book[1]"
-	     text-align="center"
-	     font-size="&hsize5;"
-	     space-before="&hsize5space;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
--->
-      <subtitle
-		text-align="center"
-		font-size="&hsize4;"
-		space-before="&hsize4space;"
-		font-family="{$title.fontset}"/>
-      <corpauthor font-size="&hsize3;"
-		  keep-with-next="always"
-		  space-before="2in"/>
-      <authorgroup space-before="2in"/>
-      <author font-size="&hsize3;"
-	      space-before="&hsize2space;"
-	      keep-with-next="always"/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-<!--
-# If you leave this block of code in then the text title in the
-# <title>BitBake User Manual</title> statement of the
-# bitbake-user-manual.xml file is rendered on the title page below the
-# image.  Commenting it out gets it out of there yet allows it
-# to be retained in the tab text for the HTML version of the
-# manual.
-
-      <title
-	     t:named-template="book.verso.title"
-	     font-size="&hsize2;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
--->
-      <corpauthor/>
-      <authorgroup t:named-template="verso.authorgroup"/>
-      <author/>
-      <othercredit/>
-      <pubdate space-before="1em"/>
-      <copyright/>
-      <abstract/>
-      <legalnotice font-size="8pt"/>
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-      <fo:block break-after="page"/>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-      <fo:block break-after="page"/>
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="part" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-      <title
-	     t:named-template="division.title"
-	     param:node="ancestor-or-self::part[1]"
-	     text-align="center"
-	     font-size="&hsize5;"
-	     space-before="&hsize5space;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    <subtitle
-	      text-align="center"
-	      font-size="&hsize4;"
-	      space-before="&hsize4space;"
-	      font-weight='bold'
-	      font-style='italic'
-	      font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="partintro" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   text-align="center"
-	   font-size="&hsize5;"
-	   font-weight="bold"
-	   space-before="1em"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      text-align="center"
-	      font-size="&hsize2;"
-	      font-weight="bold"
-	      font-style="italic"
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="reference" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-      <title
-	     t:named-template="division.title"
-	     param:node="ancestor-or-self::reference[1]"
-	     text-align="center"
-	     font-size="&hsize5;"
-	     space-before="&hsize5space;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"
-	      text-align="center"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="refsynopsisdiv" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="refsection" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="refsect1" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="refsect2" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="refsect3" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   font-family="{$title.fontset}"/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="dedication" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::dedication[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="preface" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::preface[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-      <corpauthor/>
-      <authorgroup/>
-      <author/>
-      <othercredit/>
-      <releaseinfo/>
-      <copyright/>
-      <legalnotice/>
-      <pubdate/>
-      <revision/>
-      <revhistory/>
-      <abstract/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="chapter" t:wrapper="fo:block"
-               font-family="{$title.fontset}">
-    <t:titlepage-content t:side="recto" margin-left="{$title.margin.left}">
-      <title t:named-template="component.title"
-	     param:node="ancestor-or-self::chapter[1]"
-	     font-size="&hsize5;"
-	     font-weight="bold"/>
-
-      <subtitle space-before="0.5em"
-		font-style="italic"
-		font-size="&hsize2;"
-		font-weight="bold"/>
-
-      <corpauthor  space-before="0.5em"
-	           space-after="0.5em"
-                   font-size="&hsize2;"/>
-
-      <authorgroup space-before="0.5em"
-	           space-after="0.5em"
-                   font-size="&hsize2;"/>
-
-      <author      space-before="0.5em"
-	           space-after="0.5em"
-                   font-size="&hsize2;"/>
-
-      <othercredit/>
-      <releaseinfo/>
-      <copyright/>
-      <legalnotice/>
-      <pubdate/>
-      <revision/>
-      <revhistory/>
-      <abstract/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="appendix" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::appendix[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-      <corpauthor/>
-      <authorgroup/>
-      <author/>
-      <othercredit/>
-      <releaseinfo/>
-      <copyright/>
-      <legalnotice/>
-      <pubdate/>
-      <revision/>
-      <revhistory/>
-      <abstract/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-<t:titlepage t:element="section" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="sect1" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="sect2" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="sect3" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="sect4" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="sect5" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<t:titlepage t:element="simplesect" t:wrapper="fo:block">
-  <t:titlepage-content t:side="recto">
-    <title
-	   margin-left="{$title.margin.left}"
-	   font-family="{$title.fontset}"/>
-    <subtitle
-	      font-family="{$title.fontset}"/>
-    <corpauthor/>
-    <authorgroup/>
-    <author/>
-    <othercredit/>
-    <releaseinfo/>
-    <copyright/>
-    <legalnotice/>
-    <pubdate/>
-    <revision/>
-    <revhistory/>
-    <abstract/>
-  </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="bibliography" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::bibliography[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="bibliodiv" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title t:named-template="component.title"
-	     param:node="ancestor-or-self::bibliodiv[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize4;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="glossary" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::glossary[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="glossdiv" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title t:named-template="component.title"
-	     param:node="ancestor-or-self::glossdiv[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize4;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="index" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::index[1]"
-             param:pagewide="1"
-	     margin-left="0pt"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <!-- The indexdiv.title template is used so that manual and -->
-  <!-- automatically generated indexdiv titles get the same -->
-  <!-- formatting. -->
-
-  <t:titlepage t:element="indexdiv" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title t:force="1"
-	     t:named-template="indexdiv.title"
-	     param:title="title"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="setindex" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::setindex[1]"
-             param:pagewide="1"
-	     margin-left="0pt"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="colophon" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="component.title"
-	     param:node="ancestor-or-self::colophon[1]"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize5;"
-	     font-family="{$title.fontset}"
-	     font-weight="bold"/>
-      <subtitle
-		font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-  <t:titlepage-content t:side="verso">
-  </t:titlepage-content>
-
-  <t:titlepage-separator>
-  </t:titlepage-separator>
-
-  <t:titlepage-before t:side="recto">
-  </t:titlepage-before>
-
-  <t:titlepage-before t:side="verso">
-  </t:titlepage-before>
-</t:titlepage>
-
-<!-- ==================================================================== -->
-
-  <t:titlepage t:element="table.of.contents" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'TableofContents'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.tables" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofTables'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.figures" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofFigures'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.examples" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofExamples'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.equations" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofEquations'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.procedures" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofProcedures'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-  <t:titlepage t:element="list.of.unknowns" t:wrapper="fo:block">
-    <t:titlepage-content t:side="recto">
-      <title
-	     t:force="1"
-	     t:named-template="gentext"
-	     param:key="'ListofUnknown'"
-             space-before.minimum="1em"
-             space-before.optimum="1.5em"
-             space-before.maximum="2em"
-	     space-after="0.5em"
-	     margin-left="{$title.margin.left}"
-	     font-size="&hsize3;"
-	     font-weight="bold"
-	     font-family="{$title.fontset}"/>
-    </t:titlepage-content>
-
-    <t:titlepage-content t:side="verso">
-    </t:titlepage-content>
-
-    <t:titlepage-separator>
-    </t:titlepage-separator>
-
-    <t:titlepage-before t:side="recto">
-    </t:titlepage-before>
-
-    <t:titlepage-before t:side="verso">
-    </t:titlepage-before>
-  </t:titlepage>
-
-<!-- ==================================================================== -->
-
-</t:templates>
diff --git a/bitbake/doc/tools/docbook-to-pdf b/bitbake/doc/tools/docbook-to-pdf
deleted file mode 100755
index 558ded9e..00000000
--- a/bitbake/doc/tools/docbook-to-pdf
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/sh
-	
-if [ -z "$1" -o -z "$2" ]; then
-   echo "usage: [-v] $0 <docbook file> <templatedir>"
-   echo
-   echo "*NOTE* you need xsltproc, fop and nwalsh docbook stylesheets" 
-   echo "       installed for this to work!"
-   echo
-   exit 0
-fi
-
-FO=`echo $1 | sed s/.xml/.fo/` || exit 1
-PDF=`echo $1 | sed s/.xml/.pdf/` || exit 1
-TEMPLATEDIR=$2
-
-##
-# These URI should be rewritten by your distribution's xml catalog to
-# match your localy installed XSL stylesheets.
-XSL_BASE_URI="http://docbook.sourceforge.net/release/xsl/current"
-
-# Creates a temporary XSL stylesheet based on titlepage.xsl
-xsltproc -o /tmp/titlepage.xsl                                           \
-	 --xinclude                                                      \
-         $XSL_BASE_URI/template/titlepage.xsl \
-         $TEMPLATEDIR/titlepage.templates.xml || exit 1
-
-# Creates the file needed for FOP
-xsltproc --xinclude                    \
-	 --stringparam hyphenate false \
-	 --stringparam formal.title.placement "figure after" \
-	 --stringparam ulink.show 1 \
-         --stringparam  body.font.master  9 \
-         --stringparam  title.font.master  11 \
-         --stringparam draft.watermark.image "$TEMPLATEDIR/draft.png" \
-         --stringparam  chapter.autolabel 1 \
-         --stringparam  appendix.autolabel A \
-         --stringparam  section.autolabel 1 \
-         --stringparam  section.label.includes.component.label 1 \
-         --output $FO               \
-         $TEMPLATEDIR/db-pdf.xsl    \
-	 $1                 || exit 1
-
-# Invokes the Java version of FOP.  Uses the additional configuration file common/fop-config.xml
-fop -c $TEMPLATEDIR/fop-config.xml -fo $FO -pdf $PDF       || exit 1
-
-rm -f $FO
-rm -f  /tmp/titlepage.xsl
-
-echo
-echo " #### Success! $PDF ready. ####"
-echo
diff --git a/bitbake/lib/bb/COW.py b/bitbake/lib/bb/COW.py
index bc20ce38..23c22b65 100644
--- a/bitbake/lib/bb/COW.py
+++ b/bitbake/lib/bb/COW.py
@@ -3,13 +3,14 @@
 #
 # Copyright (C) 2006 Tim Ansell
 #
-#Please Note:
+# Please Note:
 # Be careful when using mutable types (ie Dict and Lists) - operations involving these are SLOW.
 # Assign a file to __warn__ to get warnings about slow operations.
 #
 
 
 import copy
+
 ImmutableTypes = (
     bool,
     complex,
@@ -22,9 +23,11 @@ ImmutableTypes = (
 
 MUTABLE = "__mutable__"
 
+
 class COWMeta(type):
     pass
 
+
 class COWDictMeta(COWMeta):
     __warn__ = False
     __hasmutable__ = False
@@ -33,12 +36,15 @@ class COWDictMeta(COWMeta):
     def __str__(cls):
         # FIXME: I have magic numbers!
         return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
+
     __repr__ = __str__
 
     def cow(cls):
         class C(cls):
             __count__ = cls.__count__ + 1
+
         return C
+
     copy = cow
     __call__ = cow
 
@@ -70,8 +76,9 @@ class COWDictMeta(COWMeta):
         return value
 
     __getmarker__ = []
+
     def __getreadonly__(cls, key, default=__getmarker__):
-        """\
+        """
         Get a value (even if mutable) which you promise not to change.
         """
         return cls.__getitem__(key, default, True)
@@ -138,24 +145,29 @@ class COWDictMeta(COWMeta):
 
     def iterkeys(cls):
         return cls.iter("keys")
+
     def itervalues(cls, readonly=False):
         if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
-            print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
+            print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
         return cls.iter("values", readonly)
+
     def iteritems(cls, readonly=False):
         if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
-            print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
+            print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
         return cls.iter("items", readonly)
 
+
 class COWSetMeta(COWDictMeta):
     def __str__(cls):
         # FIXME: I have magic numbers!
-        return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) -3)
+        return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
+
     __repr__ = __str__
 
     def cow(cls):
         class C(cls):
             __count__ = cls.__count__ + 1
+
         return C
 
     def add(cls, value):
@@ -173,131 +185,11 @@ class COWSetMeta(COWDictMeta):
     def iteritems(cls):
         raise TypeError("sets don't have 'items'")
 
+
 # These are the actual classes you use!
-class COWDictBase(object, metaclass = COWDictMeta):
+class COWDictBase(metaclass=COWDictMeta):
     __count__ = 0
 
-class COWSetBase(object, metaclass = COWSetMeta):
-    __count__ = 0
 
-if __name__ == "__main__":
-    import sys
-    COWDictBase.__warn__ = sys.stderr
-    a = COWDictBase()
-    print("a", a)
-
-    a['a'] = 'a'
-    a['b'] = 'b'
-    a['dict'] = {}
-
-    b = a.copy()
-    print("b", b)
-    b['c'] = 'b'
-
-    print()
-
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems():
-        print(x)
-    print()
-
-    b['dict']['a'] = 'b'
-    b['a'] = 'c'
-
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems():
-        print(x)
-    print()
-
-    try:
-        b['dict2']
-    except KeyError as e:
-        print("Okay!")
-
-    a['set'] = COWSetBase()
-    a['set'].add("o1")
-    a['set'].add("o1")
-    a['set'].add("o2")
-
-    print("a", a)
-    for x in a['set'].itervalues():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b['set'].itervalues():
-        print(x)
-    print()
-
-    b['set'].add('o3')
-
-    print("a", a)
-    for x in a['set'].itervalues():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b['set'].itervalues():
-        print(x)
-    print()
-
-    a['set2'] = set()
-    a['set2'].add("o1")
-    a['set2'].add("o1")
-    a['set2'].add("o2")
-
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems(readonly=True):
-        print(x)
-    print()
-
-    del b['b']
-    try:
-        print(b['b'])
-    except KeyError:
-        print("Yay! deleted key raises error")
-
-    if 'b' in b:
-        print("Boo!")
-    else:
-        print("Yay - has_key with delete works!")
-
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems(readonly=True):
-        print(x)
-    print()
-
-    b.__revertitem__('b')
-
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems(readonly=True):
-        print(x)
-    print()
-
-    b.__revertitem__('dict')
-    print("a", a)
-    for x in a.iteritems():
-        print(x)
-    print("--")
-    print("b", b)
-    for x in b.iteritems(readonly=True):
-        print(x)
-    print()
+class COWSetBase(metaclass=COWSetMeta):
+    __count__ = 0
diff --git a/bitbake/lib/bb/__init__.py b/bitbake/lib/bb/__init__.py
index b96466e6..9f61dae1 100644
--- a/bitbake/lib/bb/__init__.py
+++ b/bitbake/lib/bb/__init__.py
@@ -9,7 +9,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
-__version__ = "1.46.0"
+__version__ = "1.50.0"
 
 import sys
 if sys.version_info < (3, 5, 0):
@@ -21,8 +21,8 @@ class BBHandledException(Exception):
     The big dilemma for generic bitbake code is what information to give the user
     when an exception occurs. Any exception inheriting this base exception class
     has already provided information to the user via some 'fired' message type such as
-    an explicitly fired event using bb.fire, or a bb.error message. If bitbake 
-    encounters an exception derived from this class, no backtrace or other information 
+    an explicitly fired event using bb.fire, or a bb.error message. If bitbake
+    encounters an exception derived from this class, no backtrace or other information
     will be given to the user, its assumed the earlier event provided the relevant information.
     """
     pass
@@ -35,19 +35,30 @@ class NullHandler(logging.Handler):
     def emit(self, record):
         pass
 
-Logger = logging.getLoggerClass()
-class BBLogger(Logger):
-    def __init__(self, name):
+class BBLoggerMixin(object):
+    def __init__(self, *args, **kwargs):
+        # Does nothing to allow calling super() from derived classes
+        pass
+
+    def setup_bblogger(self, name):
         if name.split(".")[0] == "BitBake":
-            self.debug = self.bbdebug
-        Logger.__init__(self, name)
+            self.debug = self._debug_helper
+
+    def _debug_helper(self, *args, **kwargs):
+        return self.bbdebug(1, *args, **kwargs)
+
+    def debug2(self, *args, **kwargs):
+        return self.bbdebug(2, *args, **kwargs)
+
+    def debug3(self, *args, **kwargs):
+        return self.bbdebug(3, *args, **kwargs)
 
     def bbdebug(self, level, msg, *args, **kwargs):
         loglevel = logging.DEBUG - level + 1
         if not bb.event.worker_pid:
             if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
                 return
-            if loglevel > bb.msg.loggerDefaultLogLevel:
+            if loglevel < bb.msg.loggerDefaultLogLevel:
                 return
         return self.log(loglevel, msg, *args, **kwargs)
 
@@ -60,16 +71,56 @@ class BBLogger(Logger):
     def verbnote(self, msg, *args, **kwargs):
         return self.log(logging.INFO + 2, msg, *args, **kwargs)
 
+Logger = logging.getLoggerClass()
+class BBLogger(Logger, BBLoggerMixin):
+    def __init__(self, name, *args, **kwargs):
+        self.setup_bblogger(name)
+        super().__init__(name, *args, **kwargs)
 
 logging.raiseExceptions = False
 logging.setLoggerClass(BBLogger)
 
+class BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
+    def __init__(self, logger, *args, **kwargs):
+        self.setup_bblogger(logger.name)
+        super().__init__(logger, *args, **kwargs)
+
+    if sys.version_info < (3, 6):
+        # These properties were added in Python 3.6. Add them in older versions
+        # for compatibility
+        @property
+        def manager(self):
+            return self.logger.manager
+
+        @manager.setter
+        def manager(self, value):
+            self.logger.manager = value
+
+        @property
+        def name(self):
+            return self.logger.name
+
+        def __repr__(self):
+            logger = self.logger
+            level = logger.getLevelName(logger.getEffectiveLevel())
+            return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
+
+logging.LoggerAdapter = BBLoggerAdapter
+
 logger = logging.getLogger("BitBake")
 logger.addHandler(NullHandler())
 logger.setLevel(logging.DEBUG - 2)
 
 mainlogger = logging.getLogger("BitBake.Main")
 
+class PrefixLoggerAdapter(logging.LoggerAdapter):
+    def __init__(self, prefix, logger):
+        super().__init__(logger, {})
+        self.__msg_prefix = prefix
+
+    def process(self, msg, kwargs):
+        return "%s%s" %(self.__msg_prefix, msg), kwargs
+
 # This has to be imported after the setLoggerClass, as the import of bb.msg
 # can result in construction of the various loggers.
 import bb.msg
@@ -86,7 +137,7 @@ def debug(lvl, *args):
         mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
         args = (lvl,) + args
         lvl = 1
-    mainlogger.debug(lvl, ''.join(args))
+    mainlogger.bbdebug(lvl, ''.join(args))
 
 def note(*args):
     mainlogger.info(''.join(args))
diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py
index 23b6ee45..163572be 100644
--- a/bitbake/lib/bb/build.py
+++ b/bitbake/lib/bb/build.py
@@ -16,7 +16,9 @@ import os
 import sys
 import logging
 import glob
+import itertools
 import time
+import re
 import stat
 import bb
 import bb.msg
@@ -27,6 +29,9 @@ from bb import data, event, utils
 bblogger = logging.getLogger('BitBake')
 logger = logging.getLogger('BitBake.Build')
 
+verboseShellLogging = False
+verboseStdoutLogging = False
+
 __mtime_cache = {}
 
 def cached_mtime_noerror(f):
@@ -293,6 +298,10 @@ def exec_func_python(func, d, runfile, cwd=None):
         comp = utils.better_compile(code, func, "exec_python_func() autogenerated")
         utils.better_exec(comp, {"d": d}, code, "exec_python_func() autogenerated")
     finally:
+        # We want any stdout/stderr to be printed before any other log messages to make debugging
+        # more accurate. In some cases we seem to lose stdout/stderr entirely in logging tests without this.
+        sys.stdout.flush()
+        sys.stderr.flush()
         bb.debug(2, "Python function %s finished" % func)
 
         if cwd and olddir:
@@ -303,20 +312,60 @@ def exec_func_python(func, d, runfile, cwd=None):
 
 def shell_trap_code():
     return '''#!/bin/sh\n
+__BITBAKE_LAST_LINE=0
+
 # Emit a useful diagnostic if something fails:
-bb_exit_handler() {
+bb_sh_exit_handler() {
+    ret=$?
+    if [ "$ret" != 0 ]; then
+        echo "WARNING: exit code $ret from a shell command."
+    fi
+    exit $ret
+}
+
+bb_bash_exit_handler() {
     ret=$?
-    case $ret in
-    0)  ;;
-    *)  case $BASH_VERSION in
-        "") echo "WARNING: exit code $ret from a shell command.";;
-        *)  echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from '$BASH_COMMAND'";;
-        esac
-        exit $ret
-    esac
+    { set +x; } > /dev/null
+    trap "" DEBUG
+    if [ "$ret" != 0 ]; then
+        echo "WARNING: ${BASH_SOURCE[0]}:${__BITBAKE_LAST_LINE} exit $ret from '$1'"
+
+        echo "WARNING: Backtrace (BB generated script): "
+        for i in $(seq 1 $((${#FUNCNAME[@]} - 1))); do
+            if [ "$i" -eq 1 ]; then
+                echo -e "\t#$((i)): ${FUNCNAME[$i]}, ${BASH_SOURCE[$((i-1))]}, line ${__BITBAKE_LAST_LINE}"
+            else
+                echo -e "\t#$((i)): ${FUNCNAME[$i]}, ${BASH_SOURCE[$((i-1))]}, line ${BASH_LINENO[$((i-1))]}"
+            fi
+        done
+    fi
+    exit $ret
 }
-trap 'bb_exit_handler' 0
-set -e
+
+bb_bash_debug_handler() {
+    local line=${BASH_LINENO[0]}
+    # For some reason the DEBUG trap trips with lineno=1 when scripts exit; ignore it
+    if [ "$line" -eq 1 ]; then
+        return
+    fi
+
+    # Track the line number of commands as they execute. This is so we can have access to the failing line number
+    # in the EXIT trap. See http://gnu-bash.2382.n7.nabble.com/trap-echo-quot-trap-exit-on-LINENO-quot-EXIT-gt-wrong-linenumber-td3666.html
+    if [ "${FUNCNAME[1]}" != "bb_bash_exit_handler" ]; then
+        __BITBAKE_LAST_LINE=$line
+    fi
+}
+
+case $BASH_VERSION in
+"") trap 'bb_sh_exit_handler' 0
+    set -e
+    ;;
+*)  trap 'bb_bash_exit_handler "$BASH_COMMAND"' 0
+    trap '{ bb_bash_debug_handler; } 2>/dev/null' DEBUG
+    set -e
+    shopt -s extdebug
+    ;;
+esac
 '''
 
 def create_progress_handler(func, progress, logfile, d):
@@ -346,7 +395,7 @@ def create_progress_handler(func, progress, logfile, d):
             cls_obj = functools.reduce(resolve, cls.split("."), bb.utils._context)
             if not cls_obj:
                 # Fall-back on __builtins__
-                cls_obj = functools.reduce(lambda x, y: x.get(y), cls.split("."), __builtins__)
+                cls_obj = functools.reduce(resolve, cls.split("."), __builtins__)
             if cls_obj:
                 return cls_obj(d, outfile=logfile, otherargs=otherargs)
             bb.warn('%s: unknown custom progress handler in task progress varflag value "%s", ignoring' % (func, cls))
@@ -371,7 +420,7 @@ def exec_func_shell(func, d, runfile, cwd=None):
 
         bb.data.emit_func(func, script, d)
 
-        if bb.msg.loggerVerboseLogs:
+        if verboseShellLogging or bb.utils.to_boolean(d.getVar("BB_VERBOSE_LOGS", False)):
             script.write("set -x\n")
         if cwd:
             script.write("cd '%s'\n" % cwd)
@@ -391,14 +440,20 @@ exit $ret
         if fakerootcmd:
             cmd = [fakerootcmd, runfile]
 
-    if bb.msg.loggerDefaultVerbose:
+    if verboseStdoutLogging:
         logfile = LogTee(logger, StdoutNoopContextManager())
     else:
         logfile = StdoutNoopContextManager()
 
     progress = d.getVarFlag(func, 'progress')
     if progress:
-        logfile = create_progress_handler(func, progress, logfile, d)
+        try:
+            logfile = create_progress_handler(func, progress, logfile, d)
+        except:
+            from traceback import format_exc
+            logger.error("Failed to create progress handler")
+            logger.error(format_exc())
+            raise
 
     fifobuffer = bytearray()
     def readfifo(data):
@@ -450,6 +505,62 @@ exit $ret
             bb.debug(2, "Executing shell function %s" % func)
             with open(os.devnull, 'r+') as stdin, logfile:
                 bb.process.run(cmd, shell=False, stdin=stdin, log=logfile, extrafiles=[(fifo,readfifo)])
+        except bb.process.ExecutionError as exe:
+            # Find the backtrace that the shell trap generated
+            backtrace_marker_regex = re.compile(r"WARNING: Backtrace \(BB generated script\)")
+            stdout_lines = (exe.stdout or "").split("\n")
+            backtrace_start_line = None
+            for i, line in enumerate(reversed(stdout_lines)):
+                if backtrace_marker_regex.search(line):
+                    backtrace_start_line = len(stdout_lines) - i
+                    break
+
+            # Read the backtrace frames, starting at the location we just found
+            backtrace_entry_regex = re.compile(r"#(?P<frameno>\d+): (?P<funcname>[^\s]+), (?P<file>.+?), line ("
+                                               r"?P<lineno>\d+)")
+            backtrace_frames = []
+            if backtrace_start_line:
+                for line in itertools.islice(stdout_lines, backtrace_start_line, None):
+                    match = backtrace_entry_regex.search(line)
+                    if match:
+                        backtrace_frames.append(match.groupdict())
+
+            with open(runfile, "r") as script:
+                script_lines = [line.rstrip() for line in script.readlines()]
+
+            # For each backtrace frame, search backwards in the script (from the line number called out by the frame),
+            # to find the comment that emit_vars injected when it wrote the script. This will give us the metadata
+            # filename (e.g. .bb or .bbclass) and line number where the shell function was originally defined.
+            script_metadata_comment_regex = re.compile(r"# line: (?P<lineno>\d+), file: (?P<file>.+)")
+            better_frames = []
+            # Skip the very last frame since it's just the call to the shell task in the body of the script
+            for frame in backtrace_frames[:-1]:
+                # Check whether the frame corresponds to a function defined in the script vs external script.
+                if os.path.samefile(frame["file"], runfile):
+                    # Search backwards from the frame lineno to locate the comment that BB injected
+                    i = int(frame["lineno"]) - 1
+                    while i >= 0:
+                        match = script_metadata_comment_regex.match(script_lines[i])
+                        if match:
+                            # Calculate the relative line in the function itself
+                            relative_line_in_function = int(frame["lineno"]) - i - 2
+                            # Calculate line in the function as declared in the metadata
+                            metadata_function_line = relative_line_in_function + int(match["lineno"])
+                            better_frames.append("#{frameno}: {funcname}, {file}, line {lineno}".format(
+                                frameno=frame["frameno"],
+                                funcname=frame["funcname"],
+                                file=match["file"],
+                                lineno=metadata_function_line
+                            ))
+                            break
+                        i -= 1
+                else:
+                    better_frames.append("#{frameno}: {funcname}, {file}, line {lineno}".format(**frame))
+
+            if better_frames:
+                better_frames = ("\t{0}".format(frame) for frame in better_frames)
+                exe.extra_message = "\nBacktrace (metadata-relative locations):\n{0}".format("\n".join(better_frames))
+            raise
         finally:
             os.unlink(fifopath)
 
@@ -476,7 +587,7 @@ def _exec_task(fn, task, d, quieterr):
         logger.error("No such task: %s" % task)
         return 1
 
-    logger.debug(1, "Executing task %s", task)
+    logger.debug("Executing task %s", task)
 
     localdata = _task_data(fn, task, d)
     tempdir = localdata.getVar('T')
@@ -489,7 +600,7 @@ def _exec_task(fn, task, d, quieterr):
         curnice = os.nice(0)
         nice = int(nice) - curnice
         newnice = os.nice(nice)
-        logger.debug(1, "Renice to %s " % newnice)
+        logger.debug("Renice to %s " % newnice)
     ionice = localdata.getVar("BB_TASK_IONICE_LEVEL")
     if ionice:
         try:
@@ -587,12 +698,16 @@ def _exec_task(fn, task, d, quieterr):
         except bb.BBHandledException:
             event.fire(TaskFailed(task, fn, logfn, localdata, True), localdata)
             return 1
-        except Exception as exc:
+        except (Exception, SystemExit) as exc:
             if quieterr:
                 event.fire(TaskFailedSilent(task, fn, logfn, localdata), localdata)
             else:
                 errprinted = errchk.triggered
-                logger.error(str(exc))
+                # If the output is already on stdout, we've printed the information in the
+                # logs once already so don't duplicate
+                if verboseStdoutLogging:
+                    errprinted = True
+                logger.error(repr(exc))
                 event.fire(TaskFailed(task, fn, logfn, localdata, errprinted), localdata)
             return 1
     finally:
@@ -613,7 +728,7 @@ def _exec_task(fn, task, d, quieterr):
 
         logfile.close()
         if os.path.exists(logfn) and os.path.getsize(logfn) == 0:
-            logger.debug(2, "Zero size logfn %s, removing", logfn)
+            logger.debug2("Zero size logfn %s, removing", logfn)
             bb.utils.remove(logfn)
             bb.utils.remove(loglink)
     event.fire(TaskSucceeded(task, fn, logfn, localdata), localdata)
@@ -747,6 +862,23 @@ def make_stamp(task, d, file_name = None):
         file_name = d.getVar('BB_FILENAME')
         bb.parse.siggen.dump_sigtask(file_name, task, stampbase, True)
 
+def find_stale_stamps(task, d, file_name=None):
+    current = stamp_internal(task, d, file_name)
+    current2 = stamp_internal(task + "_setscene", d, file_name)
+    cleanmask = stamp_cleanmask_internal(task, d, file_name)
+    found = []
+    for mask in cleanmask:
+        for name in glob.glob(mask):
+            if "sigdata" in name or "sigbasedata" in name:
+                continue
+            if name.endswith('.taint'):
+                continue
+            if name == current or name == current2:
+                continue
+            logger.debug2("Stampfile %s does not match %s or %s" % (name, current, current2))
+            found.append(name)
+    return found
+
 def del_stamp(task, d, file_name = None):
     """
     Removes a stamp for a given task
@@ -901,6 +1033,8 @@ def tasksbetween(task_start, task_end, d):
     def follow_chain(task, endtask, chain=None):
         if not chain:
             chain = []
+        if task in chain:
+            bb.fatal("Circular task dependencies as %s depends on itself via the chain %s" % (task, " -> ".join(chain)))
         chain.append(task)
         for othertask in tasks:
             if othertask == task:
diff --git a/bitbake/lib/bb/cache.py b/bitbake/lib/bb/cache.py
index d1be8361..27eb2717 100644
--- a/bitbake/lib/bb/cache.py
+++ b/bitbake/lib/bb/cache.py
@@ -19,16 +19,20 @@
 import os
 import logging
 import pickle
-from collections import defaultdict
+from collections import defaultdict, Mapping
 import bb.utils
+from bb import PrefixLoggerAdapter
 import re
 
 logger = logging.getLogger("BitBake.Cache")
 
-__cache_version__ = "152"
+__cache_version__ = "154"
 
-def getCacheFile(path, filename, data_hash):
-    return os.path.join(path, filename + "." + data_hash)
+def getCacheFile(path, filename, mc, data_hash):
+    mcspec = ''
+    if mc:
+        mcspec = ".%s" % mc
+    return os.path.join(path, filename + mcspec + "." + data_hash)
 
 # RecipeInfoCommon defines common data retrieving methods
 # from meta data for caches. CoreRecipeInfo as well as other
@@ -90,6 +94,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
         if not self.packages:
             self.packages.append(self.pn)
         self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
+        self.rprovides_pkg = self.pkgvar('RPROVIDES', self.packages, metadata)
 
         self.skipreason = self.getvar('__SKIPPED', metadata)
         if self.skipreason:
@@ -116,12 +121,12 @@ class CoreRecipeInfo(RecipeInfoCommon):
         self.depends          = self.depvar('DEPENDS', metadata)
         self.rdepends         = self.depvar('RDEPENDS', metadata)
         self.rrecommends      = self.depvar('RRECOMMENDS', metadata)
-        self.rprovides_pkg    = self.pkgvar('RPROVIDES', self.packages, metadata)
         self.rdepends_pkg     = self.pkgvar('RDEPENDS', self.packages, metadata)
         self.rrecommends_pkg  = self.pkgvar('RRECOMMENDS', self.packages, metadata)
         self.inherits         = self.getvar('__inherit_cache', metadata, expand=False)
         self.fakerootenv      = self.getvar('FAKEROOTENV', metadata)
         self.fakerootdirs     = self.getvar('FAKEROOTDIRS', metadata)
+        self.fakerootlogs     = self.getvar('FAKEROOTLOGS', metadata)
         self.fakerootnoenv    = self.getvar('FAKEROOTNOENV', metadata)
         self.extradepsfunc    = self.getvar('calculate_extra_depends', metadata)
 
@@ -159,6 +164,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
         cachedata.fakerootenv = {}
         cachedata.fakerootnoenv = {}
         cachedata.fakerootdirs = {}
+        cachedata.fakerootlogs = {}
         cachedata.extradepsfunc = {}
 
     def add_cacheData(self, cachedata, fn):
@@ -211,7 +217,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
         if not self.not_world:
             cachedata.possible_world.append(fn)
         #else:
-        #    logger.debug(2, "EXCLUDE FROM WORLD: %s", fn)
+        #    logger.debug2("EXCLUDE FROM WORLD: %s", fn)
 
         # create a collection of all targets for sanity checking
         # tasks, such as upstream versions, license, and tools for
@@ -227,6 +233,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
         cachedata.fakerootenv[fn] = self.fakerootenv
         cachedata.fakerootnoenv[fn] = self.fakerootnoenv
         cachedata.fakerootdirs[fn] = self.fakerootdirs
+        cachedata.fakerootlogs[fn] = self.fakerootlogs
         cachedata.extradepsfunc[fn] = self.extradepsfunc
 
 def virtualfn2realfn(virtualfn):
@@ -234,7 +241,7 @@ def virtualfn2realfn(virtualfn):
     Convert a virtual file name to a real one + the associated subclass keyword
     """
     mc = ""
-    if virtualfn.startswith('mc:'):
+    if virtualfn.startswith('mc:') and virtualfn.count(':') >= 2:
         elems = virtualfn.split(':')
         mc = elems[1]
         virtualfn = ":".join(elems[2:])
@@ -264,7 +271,7 @@ def variant2virtual(realfn, variant):
     """
     if variant == "":
         return realfn
-    if variant.startswith("mc:"):
+    if variant.startswith("mc:") and variant.count(':') >= 2:
         elems = variant.split(":")
         if elems[2]:
             return "mc:" + elems[1] + ":virtual:" + ":".join(elems[2:]) + ":" + realfn
@@ -319,12 +326,12 @@ class NoCache(object):
         Return a complete set of data for fn.
         To do this, we need to parse the file.
         """
-        logger.debug(1, "Parsing %s (full)" % virtualfn)
+        logger.debug("Parsing %s (full)" % virtualfn)
         (fn, virtual, mc) = virtualfn2realfn(virtualfn)
         bb_data = self.load_bbfile(virtualfn, appends, virtonly=True)
         return bb_data[virtual]
 
-    def load_bbfile(self, bbfile, appends, virtonly = False):
+    def load_bbfile(self, bbfile, appends, virtonly = False, mc=None):
         """
         Load and parse one .bb build file
         Return the data and whether parsing resulted in the file being skipped
@@ -337,6 +344,10 @@ class NoCache(object):
             datastores = parse_recipe(bb_data, bbfile, appends, mc)
             return datastores
 
+        if mc is not None:
+            bb_data = self.databuilder.mcdata[mc].createCopy()
+            return parse_recipe(bb_data, bbfile, appends, mc)
+
         bb_data = self.data.createCopy()
         datastores = parse_recipe(bb_data, bbfile, appends)
 
@@ -354,14 +365,15 @@ class Cache(NoCache):
     """
     BitBake Cache implementation
     """
-
-    def __init__(self, databuilder, data_hash, caches_array):
+    def __init__(self, databuilder, mc, data_hash, caches_array):
         super().__init__(databuilder)
         data = databuilder.data
 
         # Pass caches_array information into Cache Constructor
         # It will be used later for deciding whether we
         # need extra cache file dump/load support
+        self.mc = mc
+        self.logger = PrefixLoggerAdapter("Cache: %s: " % (mc if mc else "default"), logger)
         self.caches_array = caches_array
         self.cachedir = data.getVar("CACHE")
         self.clean = set()
@@ -374,31 +386,47 @@ class Cache(NoCache):
 
         if self.cachedir in [None, '']:
             self.has_cache = False
-            logger.info("Not using a cache. "
-                        "Set CACHE = <directory> to enable.")
+            self.logger.info("Not using a cache. "
+                             "Set CACHE = <directory> to enable.")
             return
 
         self.has_cache = True
-        self.cachefile = getCacheFile(self.cachedir, "bb_cache.dat", self.data_hash)
 
-        logger.debug(1, "Cache dir: %s", self.cachedir)
+    def getCacheFile(self, cachefile):
+        return getCacheFile(self.cachedir, cachefile, self.mc, self.data_hash)
+
+    def prepare_cache(self, progress):
+        if not self.has_cache:
+            return 0
+
+        loaded = 0
+
+        self.cachefile = self.getCacheFile("bb_cache.dat")
+
+        self.logger.debug("Cache dir: %s", self.cachedir)
         bb.utils.mkdirhier(self.cachedir)
 
         cache_ok = True
         if self.caches_array:
             for cache_class in self.caches_array:
-                cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
-                cache_ok = cache_ok and os.path.exists(cachefile)
+                cachefile = self.getCacheFile(cache_class.cachefile)
+                cache_exists = os.path.exists(cachefile)
+                self.logger.debug2("Checking if %s exists: %r", cachefile, cache_exists)
+                cache_ok = cache_ok and cache_exists
                 cache_class.init_cacheData(self)
         if cache_ok:
-            self.load_cachefile()
+            loaded = self.load_cachefile(progress)
         elif os.path.isfile(self.cachefile):
-            logger.info("Out of date cache found, rebuilding...")
+            self.logger.info("Out of date cache found, rebuilding...")
         else:
-            logger.debug(1, "Cache file %s not found, building..." % self.cachefile)
+            self.logger.debug("Cache file %s not found, building..." % self.cachefile)
 
         # We don't use the symlink, its just for debugging convinience
-        symlink = os.path.join(self.cachedir, "bb_cache.dat")
+        if self.mc:
+            symlink = os.path.join(self.cachedir, "bb_cache.dat.%s" % self.mc)
+        else:
+            symlink = os.path.join(self.cachedir, "bb_cache.dat")
+
         if os.path.exists(symlink):
             bb.utils.remove(symlink)
         try:
@@ -406,22 +434,29 @@ class Cache(NoCache):
         except OSError:
             pass
 
-    def load_cachefile(self):
-        cachesize = 0
-        previous_progress = 0
-        previous_percent = 0
+        return loaded
 
-        # Calculate the correct cachesize of all those cache files
+    def cachesize(self):
+        if not self.has_cache:
+            return 0
+
+        cachesize = 0
         for cache_class in self.caches_array:
-            cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
-            with open(cachefile, "rb") as cachefile:
-                cachesize += os.fstat(cachefile.fileno()).st_size
+            cachefile = self.getCacheFile(cache_class.cachefile)
+            try:
+                with open(cachefile, "rb") as cachefile:
+                    cachesize += os.fstat(cachefile.fileno()).st_size
+            except FileNotFoundError:
+                pass
 
-        bb.event.fire(bb.event.CacheLoadStarted(cachesize), self.data)
+        return cachesize
+
+    def load_cachefile(self, progress):
+        previous_progress = 0
 
         for cache_class in self.caches_array:
-            cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
-            logger.debug(1, 'Loading cache file: %s' % cachefile)
+            cachefile = self.getCacheFile(cache_class.cachefile)
+            self.logger.debug('Loading cache file: %s' % cachefile)
             with open(cachefile, "rb") as cachefile:
                 pickled = pickle.Unpickler(cachefile)
                 # Check cache version information
@@ -429,15 +464,15 @@ class Cache(NoCache):
                     cache_ver = pickled.load()
                     bitbake_ver = pickled.load()
                 except Exception:
-                    logger.info('Invalid cache, rebuilding...')
-                    return
+                    self.logger.info('Invalid cache, rebuilding...')
+                    return 0
 
                 if cache_ver != __cache_version__:
-                    logger.info('Cache version mismatch, rebuilding...')
-                    return
+                    self.logger.info('Cache version mismatch, rebuilding...')
+                    return 0
                 elif bitbake_ver != bb.__version__:
-                    logger.info('Bitbake version mismatch, rebuilding...')
-                    return
+                    self.logger.info('Bitbake version mismatch, rebuilding...')
+                    return 0
 
                 # Load the rest of the cache file
                 current_progress = 0
@@ -460,29 +495,17 @@ class Cache(NoCache):
                         self.depends_cache[key] = [value]
                     # only fire events on even percentage boundaries
                     current_progress = cachefile.tell() + previous_progress
-                    if current_progress > cachesize:
-                        # we might have calculated incorrect total size because a file
-                        # might've been written out just after we checked its size
-                        cachesize = current_progress
-                    current_percent = 100 * current_progress / cachesize
-                    if current_percent > previous_percent:
-                        previous_percent = current_percent
-                        bb.event.fire(bb.event.CacheLoadProgress(current_progress, cachesize),
-                                      self.data)
+                    progress(cachefile.tell() + previous_progress)
 
                 previous_progress += current_progress
 
-        # Note: depends cache number is corresponding to the parsing file numbers.
-        # The same file has several caches, still regarded as one item in the cache
-        bb.event.fire(bb.event.CacheLoadCompleted(cachesize,
-                                                  len(self.depends_cache)),
-                      self.data)
+        return len(self.depends_cache)
 
     def parse(self, filename, appends):
         """Parse the specified filename, returning the recipe information"""
-        logger.debug(1, "Parsing %s", filename)
+        self.logger.debug("Parsing %s", filename)
         infos = []
-        datastores = self.load_bbfile(filename, appends)
+        datastores = self.load_bbfile(filename, appends, mc=self.mc)
         depends = []
         variants = []
         # Process the "real" fn last so we can store variants list
@@ -534,7 +557,7 @@ class Cache(NoCache):
         cached, infos = self.load(fn, appends)
         for virtualfn, info_array in infos:
             if info_array[0].skipped:
-                logger.debug(1, "Skipping %s: %s", virtualfn, info_array[0].skipreason)
+                self.logger.debug("Skipping %s: %s", virtualfn, info_array[0].skipreason)
                 skipped += 1
             else:
                 self.add_info(virtualfn, info_array, cacheData, not cached)
@@ -570,21 +593,21 @@ class Cache(NoCache):
 
         # File isn't in depends_cache
         if not fn in self.depends_cache:
-            logger.debug(2, "Cache: %s is not cached", fn)
+            self.logger.debug2("%s is not cached", fn)
             return False
 
         mtime = bb.parse.cached_mtime_noerror(fn)
 
         # Check file still exists
         if mtime == 0:
-            logger.debug(2, "Cache: %s no longer exists", fn)
+            self.logger.debug2("%s no longer exists", fn)
             self.remove(fn)
             return False
 
         info_array = self.depends_cache[fn]
         # Check the file's timestamp
         if mtime != info_array[0].timestamp:
-            logger.debug(2, "Cache: %s changed", fn)
+            self.logger.debug2("%s changed", fn)
             self.remove(fn)
             return False
 
@@ -595,14 +618,14 @@ class Cache(NoCache):
                 fmtime = bb.parse.cached_mtime_noerror(f)
                 # Check if file still exists
                 if old_mtime != 0 and fmtime == 0:
-                    logger.debug(2, "Cache: %s's dependency %s was removed",
-                                    fn, f)
+                    self.logger.debug2("%s's dependency %s was removed",
+                                         fn, f)
                     self.remove(fn)
                     return False
 
                 if (fmtime != old_mtime):
-                    logger.debug(2, "Cache: %s's dependency %s changed",
-                                    fn, f)
+                    self.logger.debug2("%s's dependency %s changed",
+                                         fn, f)
                     self.remove(fn)
                     return False
 
@@ -614,18 +637,18 @@ class Cache(NoCache):
                 # Have to be careful about spaces and colons in filenames
                 flist = self.filelist_regex.split(fl)
                 for f in flist:
-                    if not f or "*" in f:
+                    if not f:
                         continue
                     f, exist = f.split(":")
                     if (exist == "True" and not os.path.exists(f)) or (exist == "False" and os.path.exists(f)):
-                        logger.debug(2, "Cache: %s's file checksum list file %s changed",
-                                        fn, f)
+                        self.logger.debug2("%s's file checksum list file %s changed",
+                                             fn, f)
                         self.remove(fn)
                         return False
 
-        if appends != info_array[0].appends:
-            logger.debug(2, "Cache: appends for %s changed", fn)
-            logger.debug(2, "%s to %s" % (str(appends), str(info_array[0].appends)))
+        if tuple(appends) != tuple(info_array[0].appends):
+            self.logger.debug2("appends for %s changed", fn)
+            self.logger.debug2("%s to %s" % (str(appends), str(info_array[0].appends)))
             self.remove(fn)
             return False
 
@@ -634,10 +657,10 @@ class Cache(NoCache):
             virtualfn = variant2virtual(fn, cls)
             self.clean.add(virtualfn)
             if virtualfn not in self.depends_cache:
-                logger.debug(2, "Cache: %s is not cached", virtualfn)
+                self.logger.debug2("%s is not cached", virtualfn)
                 invalid = True
             elif len(self.depends_cache[virtualfn]) != len(self.caches_array):
-                logger.debug(2, "Cache: Extra caches missing for %s?" % virtualfn)
+                self.logger.debug2("Extra caches missing for %s?" % virtualfn)
                 invalid = True
 
         # If any one of the variants is not present, mark as invalid for all
@@ -645,10 +668,10 @@ class Cache(NoCache):
             for cls in info_array[0].variants:
                 virtualfn = variant2virtual(fn, cls)
                 if virtualfn in self.clean:
-                    logger.debug(2, "Cache: Removing %s from cache", virtualfn)
+                    self.logger.debug2("Removing %s from cache", virtualfn)
                     self.clean.remove(virtualfn)
             if fn in self.clean:
-                logger.debug(2, "Cache: Marking %s as not clean", fn)
+                self.logger.debug2("Marking %s as not clean", fn)
                 self.clean.remove(fn)
             return False
 
@@ -661,10 +684,10 @@ class Cache(NoCache):
         Called from the parser in error cases
         """
         if fn in self.depends_cache:
-            logger.debug(1, "Removing %s from cache", fn)
+            self.logger.debug("Removing %s from cache", fn)
             del self.depends_cache[fn]
         if fn in self.clean:
-            logger.debug(1, "Marking %s as unclean", fn)
+            self.logger.debug("Marking %s as unclean", fn)
             self.clean.remove(fn)
 
     def sync(self):
@@ -677,12 +700,13 @@ class Cache(NoCache):
             return
 
         if self.cacheclean:
-            logger.debug(2, "Cache is clean, not saving.")
+            self.logger.debug2("Cache is clean, not saving.")
             return
 
         for cache_class in self.caches_array:
             cache_class_name = cache_class.__name__
-            cachefile = getCacheFile(self.cachedir, cache_class.cachefile, self.data_hash)
+            cachefile = self.getCacheFile(cache_class.cachefile)
+            self.logger.debug2("Writing %s", cachefile)
             with open(cachefile, "wb") as f:
                 p = pickle.Pickler(f, pickle.HIGHEST_PROTOCOL)
                 p.dump(__cache_version__)
@@ -701,8 +725,18 @@ class Cache(NoCache):
         return bb.parse.cached_mtime_noerror(cachefile)
 
     def add_info(self, filename, info_array, cacheData, parsed=None, watcher=None):
+        if self.mc is not None:
+            (fn, cls, mc) = virtualfn2realfn(filename)
+            if mc:
+                self.logger.error("Unexpected multiconfig %s", filename)
+                return
+
+            vfn = realfn2virtual(fn, cls, self.mc)
+        else:
+            vfn = filename
+
         if isinstance(info_array[0], CoreRecipeInfo) and (not info_array[0].skipped):
-            cacheData.add_from_recipeinfo(filename, info_array)
+            cacheData.add_from_recipeinfo(vfn, info_array)
 
             if watcher:
                 watcher(info_array[0].file_depends)
@@ -727,6 +761,61 @@ class Cache(NoCache):
             info_array.append(cache_class(realfn, data))
         self.add_info(file_name, info_array, cacheData, parsed)
 
+class MulticonfigCache(Mapping):
+    def __init__(self, databuilder, data_hash, caches_array):
+        def progress(p):
+            nonlocal current_progress
+            nonlocal previous_progress
+            nonlocal previous_percent
+            nonlocal cachesize
+
+            current_progress = previous_progress + p
+
+            if current_progress > cachesize:
+                # we might have calculated incorrect total size because a file
+                # might've been written out just after we checked its size
+                cachesize = current_progress
+            current_percent = 100 * current_progress / cachesize
+            if current_percent > previous_percent:
+                previous_percent = current_percent
+                bb.event.fire(bb.event.CacheLoadProgress(current_progress, cachesize),
+                                databuilder.data)
+
+
+        cachesize = 0
+        current_progress = 0
+        previous_progress = 0
+        previous_percent = 0
+        self.__caches = {}
+
+        for mc, mcdata in databuilder.mcdata.items():
+            self.__caches[mc] = Cache(databuilder, mc, data_hash, caches_array)
+
+            cachesize += self.__caches[mc].cachesize()
+
+        bb.event.fire(bb.event.CacheLoadStarted(cachesize), databuilder.data)
+        loaded = 0
+
+        for c in self.__caches.values():
+            loaded += c.prepare_cache(progress)
+            previous_progress = current_progress
+
+        # Note: depends cache number is corresponding to the parsing file numbers.
+        # The same file has several caches, still regarded as one item in the cache
+        bb.event.fire(bb.event.CacheLoadCompleted(cachesize, loaded), databuilder.data)
+
+    def __len__(self):
+        return len(self.__caches)
+
+    def __getitem__(self, key):
+        return self.__caches[key]
+
+    def __contains__(self, key):
+        return key in self.__caches
+
+    def __iter__(self):
+        for k in self.__caches:
+            yield k
 
 def init(cooker):
     """
@@ -793,7 +882,7 @@ class MultiProcessCache(object):
         bb.utils.mkdirhier(cachedir)
         self.cachefile = os.path.join(cachedir,
                                       cache_file_name or self.__class__.cache_file_name)
-        logger.debug(1, "Using cache in '%s'", self.cachefile)
+        logger.debug("Using cache in '%s'", self.cachefile)
 
         glf = bb.utils.lockfile(self.cachefile + ".lock")
 
@@ -899,7 +988,7 @@ class SimpleCache(object):
         bb.utils.mkdirhier(cachedir)
         self.cachefile = os.path.join(cachedir,
                                       cache_file_name or self.__class__.cache_file_name)
-        logger.debug(1, "Using cache in '%s'", self.cachefile)
+        logger.debug("Using cache in '%s'", self.cachefile)
 
         glf = bb.utils.lockfile(self.cachefile + ".lock")
 
diff --git a/bitbake/lib/bb/codeparser.py b/bitbake/lib/bb/codeparser.py
index 25a7ac69..0cec452c 100644
--- a/bitbake/lib/bb/codeparser.py
+++ b/bitbake/lib/bb/codeparser.py
@@ -212,9 +212,9 @@ class PythonParser():
             funcstr = codegen.to_source(func)
             argstr = codegen.to_source(arg)
         except TypeError:
-            self.log.debug(2, 'Failed to convert function and argument to source form')
+            self.log.debug2('Failed to convert function and argument to source form')
         else:
-            self.log.debug(1, self.unhandled_message % (funcstr, argstr))
+            self.log.debug(self.unhandled_message % (funcstr, argstr))
 
     def visit_Call(self, node):
         name = self.called_node_name(node.func)
@@ -450,7 +450,7 @@ class ShellParser():
 
                 cmd = word[1]
                 if cmd.startswith("$"):
-                    self.log.debug(1, self.unhandled_template % cmd)
+                    self.log.debug(self.unhandled_template % cmd)
                 elif cmd == "eval":
                     command = " ".join(word for _, word in words[1:])
                     self._parse_shell(command)
diff --git a/bitbake/lib/bb/command.py b/bitbake/lib/bb/command.py
index 6abf3866..dd77cdd6 100644
--- a/bitbake/lib/bb/command.py
+++ b/bitbake/lib/bb/command.py
@@ -54,13 +54,20 @@ class Command:
         self.cooker = cooker
         self.cmds_sync = CommandsSync()
         self.cmds_async = CommandsAsync()
-        self.remotedatastores = bb.remotedata.RemoteDatastores(cooker)
+        self.remotedatastores = None
 
         # FIXME Add lock for this
         self.currentAsyncCommand = None
 
     def runCommand(self, commandline, ro_only = False):
         command = commandline.pop(0)
+
+        # Ensure cooker is ready for commands
+        if command != "updateConfig" and command != "setFeatures":
+            self.cooker.init_configdata()
+            if not self.remotedatastores:
+                self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
+
         if hasattr(CommandsSync, command):
             # Can run synchronous commands straight away
             command_method = getattr(self.cmds_sync, command)
@@ -74,8 +81,12 @@ class Command:
                 result = command_method(self, commandline)
             except CommandError as exc:
                 return None, exc.args[0]
-            except (Exception, SystemExit):
+            except (Exception, SystemExit) as exc:
                 import traceback
+                if isinstance(exc, bb.BBHandledException):
+                    # We need to start returning real exceptions here. Until we do, we can't
+                    # tell if an exception is an instance of bb.BBHandledException
+                    return None, "bb.BBHandledException()\n" + traceback.format_exc()
                 return None, traceback.format_exc()
             else:
                 return result, None
@@ -84,7 +95,7 @@ class Command:
         if command not in CommandsAsync.__dict__:
             return None, "No such command"
         self.currentAsyncCommand = (command, commandline)
-        self.cooker.configuration.server_register_idlecallback(self.cooker.runCommands, self.cooker)
+        self.cooker.idleCallBackRegister(self.cooker.runCommands, self.cooker)
         return True, None
 
     def runAsyncCommand(self):
@@ -136,13 +147,8 @@ class Command:
         self.cooker.finishcommand()
 
     def reset(self):
-        self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
-
-def split_mc_pn(pn):
-    if pn.startswith("multiconfig:"):
-        _, mc, pn = pn.split(":", 2)
-        return (mc, pn)
-    return ('', pn)
+        if self.remotedatastores:
+           self.remotedatastores = bb.remotedata.RemoteDatastores(self.cooker)
 
 class CommandsSync:
     """
@@ -232,7 +238,11 @@ class CommandsSync:
 
     def matchFile(self, command, params):
         fMatch = params[0]
-        return command.cooker.matchFile(fMatch)
+        try:
+            mc = params[0]
+        except IndexError:
+            mc = ''
+        return command.cooker.matchFile(fMatch, mc)
     matchFile.needconfig = False
 
     def getUIHandlerNum(self, command, params):
@@ -395,22 +405,38 @@ class CommandsSync:
     def getSkippedRecipes(self, command, params):
         # Return list sorted by reverse priority order
         import bb.cache
-        skipdict = OrderedDict(sorted(command.cooker.skiplist.items(),
-                                      key=lambda x: (-command.cooker.collection.calc_bbfile_priority(bb.cache.virtualfn2realfn(x[0])[0]), x[0])))
+        def sortkey(x):
+            vfn, _ = x
+            realfn, _, mc = bb.cache.virtualfn2realfn(vfn)
+            return (-command.cooker.collections[mc].calc_bbfile_priority(realfn)[0], vfn)
+
+        skipdict = OrderedDict(sorted(command.cooker.skiplist.items(), key=sortkey))
         return list(skipdict.items())
     getSkippedRecipes.readonly = True
 
     def getOverlayedRecipes(self, command, params):
-        return list(command.cooker.collection.overlayed.items())
+        try:
+            mc = params[0]
+        except IndexError:
+            mc = ''
+        return list(command.cooker.collections[mc].overlayed.items())
     getOverlayedRecipes.readonly = True
 
     def getFileAppends(self, command, params):
         fn = params[0]
-        return command.cooker.collection.get_file_appends(fn)
+        try:
+            mc = params[1]
+        except IndexError:
+            mc = ''
+        return command.cooker.collections[mc].get_file_appends(fn)
     getFileAppends.readonly = True
 
     def getAllAppends(self, command, params):
-        return command.cooker.collection.bbappends
+        try:
+            mc = params[0]
+        except IndexError:
+            mc = ''
+        return command.cooker.collections[mc].bbappends
     getAllAppends.readonly = True
 
     def findProviders(self, command, params):
@@ -422,7 +448,7 @@ class CommandsSync:
     findProviders.readonly = True
 
     def findBestProvider(self, command, params):
-        (mc, pn) = split_mc_pn(params[0])
+        (mc, pn) = bb.runqueue.split_mc(params[0])
         return command.cooker.findBestProvider(pn, mc)
     findBestProvider.readonly = True
 
@@ -496,6 +522,7 @@ class CommandsSync:
         for the recipe.
         """
         fn = params[0]
+        mc = bb.runqueue.mc_from_tid(fn)
         appends = params[1]
         appendlist = params[2]
         if len(params) > 3:
@@ -507,7 +534,7 @@ class CommandsSync:
             if appendlist is not None:
                 appendfiles = appendlist
             else:
-                appendfiles = command.cooker.collection.get_file_appends(fn)
+                appendfiles = command.cooker.collections[mc].get_file_appends(fn)
         else:
             appendfiles = []
         # We are calling bb.cache locally here rather than on the server,
@@ -517,7 +544,7 @@ class CommandsSync:
         if config_data:
             # We have to use a different function here if we're passing in a datastore
             # NOTE: we took a copy above, so we don't do it here again
-            envdata = bb.cache.parse_recipe(config_data, fn, appendfiles)['']
+            envdata = bb.cache.parse_recipe(config_data, fn, appendfiles, mc)['']
         else:
             # Use the standard path
             parser = bb.cache.NoCache(command.cooker.databuilder)
@@ -708,10 +735,10 @@ class CommandsAsync:
         """
         Find signature info files via the signature generator
         """
-        pn = params[0]
+        (mc, pn) = bb.runqueue.split_mc(params[0])
         taskname = params[1]
         sigs = params[2]
-        res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.data)
-        bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.data)
+        res = bb.siggen.find_siginfo(pn, taskname, sigs, command.cooker.databuilder.mcdata[mc])
+        bb.event.fire(bb.event.FindSigInfoResult(res), command.cooker.databuilder.mcdata[mc])
         command.finishAsyncCommand()
     findSigInfo.needcache = False
diff --git a/bitbake/lib/bb/compat.py b/bitbake/lib/bb/compat.py
deleted file mode 100644
index 49356681..00000000
--- a/bitbake/lib/bb/compat.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# SPDX-License-Identifier: GPL-2.0-only
-#
-
-"""Code pulled from future python versions, here for compatibility"""
-
-from collections import MutableMapping, KeysView, ValuesView, ItemsView, OrderedDict
-from functools import total_ordering
-
-
diff --git a/bitbake/lib/bb/cooker.py b/bitbake/lib/bb/cooker.py
index d90bd394..89f1fad0 100644
--- a/bitbake/lib/bb/cooker.py
+++ b/bitbake/lib/bb/cooker.py
@@ -73,7 +73,9 @@ class SkippedPackage:
             self.pn = info.pn
             self.skipreason = info.skipreason
             self.provides = info.provides
-            self.rprovides = info.rprovides
+            self.rprovides = info.packages + info.rprovides
+            for package in info.packages:
+                self.rprovides += info.rprovides_pkg[package]
         elif reason:
             self.skipreason = reason
 
@@ -148,15 +150,18 @@ class BBCooker:
     Manages one bitbake build run
     """
 
-    def __init__(self, configuration, featureSet=None):
+    def __init__(self, featureSet=None, idleCallBackRegister=None):
         self.recipecaches = None
+        self.eventlog = None
         self.skiplist = {}
         self.featureset = CookerFeatures()
         if featureSet:
             for f in featureSet:
                 self.featureset.setFeature(f)
 
-        self.configuration = configuration
+        self.configuration = bb.cookerdata.CookerConfiguration()
+
+        self.idleCallBackRegister = idleCallBackRegister
 
         bb.debug(1, "BBCooker starting %s" % time.time())
         sys.stdout.flush()
@@ -192,25 +197,13 @@ class BBCooker:
         self.hashserv = None
         self.hashservaddr = None
 
-        self.initConfigurationData()
-
-        bb.debug(1, "BBCooker parsed base configuration %s" % time.time())
-        sys.stdout.flush()
-
-        # we log all events to a file if so directed
-        if self.configuration.writeeventlog:
-            # register the log file writer as UI Handler
-            writer = EventWriter(self, self.configuration.writeeventlog)
-            EventLogWriteHandler = namedtuple('EventLogWriteHandler', ['event'])
-            bb.event.register_UIHhandler(EventLogWriteHandler(writer))
-
         self.inotify_modified_files = []
 
         def _process_inotify_updates(server, cooker, abort):
             cooker.process_inotify_updates()
             return 1.0
 
-        self.configuration.server_register_idlecallback(_process_inotify_updates, self)
+        self.idleCallBackRegister(_process_inotify_updates, self)
 
         # TOSTOP must not be set or our children will hang when they output
         try:
@@ -237,6 +230,13 @@ class BBCooker:
         bb.debug(1, "BBCooker startup complete %s" % time.time())
         sys.stdout.flush()
 
+    def init_configdata(self):
+        if not hasattr(self, "data"):
+            self.initConfigurationData()
+            bb.debug(1, "BBCooker parsed base configuration %s" % time.time())
+            sys.stdout.flush()
+            self.handlePRServ()
+
     def process_inotify_updates(self):
         for n in [self.confignotifier, self.notifier]:
             if n.check_events(timeout=0):
@@ -322,7 +322,7 @@ class BBCooker:
         for feature in features:
             self.featureset.setFeature(feature)
         bb.debug(1, "Features set %s (was %s)" % (original_featureset, list(self.featureset)))
-        if (original_featureset != list(self.featureset)) and self.state != state.error:
+        if (original_featureset != list(self.featureset)) and self.state != state.error and hasattr(self, "data"):
             self.reset()
 
     def initConfigurationData(self):
@@ -354,7 +354,7 @@ class BBCooker:
                 self.caches_array.append(getattr(module, cache_name))
             except ImportError as exc:
                 logger.critical("Unable to import extra RecipeInfo '%s' from '%s': %s" % (cache_name, module_name, exc))
-                sys.exit("FATAL: Failed to import extra cache class '%s'." % cache_name)
+                raise bb.BBHandledException()
 
         self.databuilder = bb.cookerdata.CookerDataBuilder(self.configuration, False)
         self.databuilder.parseBaseConfiguration()
@@ -382,14 +382,19 @@ class BBCooker:
         try:
             self.prhost = prserv.serv.auto_start(self.data)
         except prserv.serv.PRServiceConfigError as e:
-            bb.fatal("Unable to start PR Server, exitting")
+            bb.fatal("Unable to start PR Server, exiting")
 
         if self.data.getVar("BB_HASHSERVE") == "auto":
             # Create a new hash server bound to a unix domain socket
             if not self.hashserv:
                 dbfile = (self.data.getVar("PERSISTENT_DIR") or self.data.getVar("CACHE")) + "/hashserv.db"
                 self.hashservaddr = "unix://%s/hashserve.sock" % self.data.getVar("TOPDIR")
-                self.hashserv = hashserv.create_server(self.hashservaddr, dbfile, sync=False)
+                self.hashserv = hashserv.create_server(
+                    self.hashservaddr,
+                    dbfile,
+                    sync=False,
+                    upstream=self.data.getVar("BB_HASHSERVE_UPSTREAM") or None,
+                )
                 self.hashserv.process = multiprocessing.Process(target=self.hashserv.serve_forever)
                 self.hashserv.process.start()
             self.data.setVar("BB_HASHSERVE", self.hashservaddr)
@@ -411,10 +416,7 @@ class BBCooker:
             self.data.disableTracking()
 
     def parseConfiguration(self):
-        # Set log file verbosity
-        verboselogs = bb.utils.to_boolean(self.data.getVar("BB_VERBOSE_LOGS", False))
-        if verboselogs:
-            bb.msg.loggerVerboseLogs = True
+        self.updateCacheSync()
 
         # Change nice level if we're asked to
         nice = self.data.getVar("BB_NICE_LEVEL")
@@ -446,27 +448,52 @@ class BBCooker:
                         continue
                 except AttributeError:
                     pass
-                logger.debug(1, "Marking as dirty due to '%s' option change to '%s'" % (o, options[o]))
+                logger.debug("Marking as dirty due to '%s' option change to '%s'" % (o, options[o]))
                 print("Marking as dirty due to '%s' option change to '%s'" % (o, options[o]))
                 clean = False
-            setattr(self.configuration, o, options[o])
+            if hasattr(self.configuration, o):
+                setattr(self.configuration, o, options[o])
+
+        if self.configuration.writeeventlog:
+            if self.eventlog and self.eventlog[0] != self.configuration.writeeventlog:
+                bb.event.unregister_UIHhandler(self.eventlog[1])
+            if not self.eventlog or self.eventlog[0] != self.configuration.writeeventlog:
+                # we log all events to a file if so directed
+                # register the log file writer as UI Handler
+                writer = EventWriter(self, self.configuration.writeeventlog)
+                EventLogWriteHandler = namedtuple('EventLogWriteHandler', ['event'])
+                self.eventlog = (self.configuration.writeeventlog, bb.event.register_UIHhandler(EventLogWriteHandler(writer)))
+
+        bb.msg.loggerDefaultLogLevel = self.configuration.default_loglevel
+        bb.msg.loggerDefaultDomains = self.configuration.debug_domains
+
+        if hasattr(self, "data"):
+            origenv = bb.data.init()
+            for k in environment:
+                origenv.setVar(k, environment[k])
+            self.data.setVar("BB_ORIGENV", origenv)
+
         for k in bb.utils.approved_variables():
             if k in environment and k not in self.configuration.env:
-                logger.debug(1, "Updating new environment variable %s to %s" % (k, environment[k]))
+                logger.debug("Updating new environment variable %s to %s" % (k, environment[k]))
                 self.configuration.env[k] = environment[k]
                 clean = False
             if k in self.configuration.env and k not in environment:
-                logger.debug(1, "Updating environment variable %s (deleted)" % (k))
+                logger.debug("Updating environment variable %s (deleted)" % (k))
                 del self.configuration.env[k]
                 clean = False
             if k not in self.configuration.env and k not in environment:
                 continue
             if environment[k] != self.configuration.env[k]:
-                logger.debug(1, "Updating environment variable %s from %s to %s" % (k, self.configuration.env[k], environment[k]))
+                logger.debug("Updating environment variable %s from %s to %s" % (k, self.configuration.env[k], environment[k]))
                 self.configuration.env[k] = environment[k]
                 clean = False
+
+        # Now update all the variables not in the datastore to match
+        self.configuration.env = environment
+
         if not clean:
-            logger.debug(1, "Base environment change, triggering reparse")
+            logger.debug("Base environment change, triggering reparse")
             self.reset()
 
     def runCommands(self, server, data, abort):
@@ -480,22 +507,30 @@ class BBCooker:
 
     def showVersions(self):
 
-        (latest_versions, preferred_versions) = self.findProviders()
+        (latest_versions, preferred_versions, required) = self.findProviders()
 
-        logger.plain("%-35s %25s %25s", "Recipe Name", "Latest Version", "Preferred Version")
-        logger.plain("%-35s %25s %25s\n", "===========", "==============", "=================")
+        logger.plain("%-35s %25s %25s %25s", "Recipe Name", "Latest Version", "Preferred Version", "Required Version")
+        logger.plain("%-35s %25s %25s %25s\n", "===========", "==============", "=================", "================")
 
         for p in sorted(self.recipecaches[''].pkg_pn):
-            pref = preferred_versions[p]
+            preferred = preferred_versions[p]
             latest = latest_versions[p]
+            requiredstr = ""
+            preferredstr = ""
+            if required[p]:
+                if preferred[0] is not None:
+                    requiredstr = preferred[0][0] + ":" + preferred[0][1] + '-' + preferred[0][2]
+                else:
+                    bb.fatal("REQUIRED_VERSION of package %s not available" % p)
+            else:
+                preferredstr = preferred[0][0] + ":" + preferred[0][1] + '-' + preferred[0][2]
 
-            prefstr = pref[0][0] + ":" + pref[0][1] + '-' + pref[0][2]
             lateststr = latest[0][0] + ":" + latest[0][1] + "-" + latest[0][2]
 
-            if pref == latest:
-                prefstr = ""
+            if preferred == latest:
+                preferredstr = ""
 
-            logger.plain("%-35s %25s %25s", p, lateststr, prefstr)
+            logger.plain("%-35s %25s %25s %25s", p, lateststr, preferredstr, requiredstr)
 
     def showEnvironment(self, buildfile=None, pkgs_to_build=None):
         """
@@ -525,7 +560,7 @@ class BBCooker:
             self.parseConfiguration()
 
             fn, cls, mc = bb.cache.virtualfn2realfn(buildfile)
-            fn = self.matchFile(fn)
+            fn = self.matchFile(fn, mc)
             fn = bb.cache.realfn2virtual(fn, cls, mc)
         elif len(pkgs_to_build) == 1:
             mc = mc_base(pkgs_to_build[0])
@@ -541,8 +576,8 @@ class BBCooker:
 
         if fn:
             try:
-                bb_cache = bb.cache.Cache(self.databuilder, self.data_hash, self.caches_array)
-                envdata = bb_cache.loadDataFull(fn, self.collection.get_file_appends(fn))
+                bb_caches = bb.cache.MulticonfigCache(self.databuilder, self.data_hash, self.caches_array)
+                envdata = bb_caches[mc].loadDataFull(fn, self.collections[mc].get_file_appends(fn))
             except Exception as e:
                 parselog.exception("Unable to read %s", fn)
                 raise
@@ -594,7 +629,7 @@ class BBCooker:
         # Replace string such as "mc:*:bash"
         # into "mc:A:bash mc:B:bash bash"
         for k in targetlist:
-            if k.startswith("mc:"):
+            if k.startswith("mc:") and k.count(':') >= 2:
                 if wildcard:
                     bb.fatal('multiconfig conflict')
                 if k.split(":")[1] == "*":
@@ -626,8 +661,9 @@ class BBCooker:
         current = 0
         runlist = []
         for k in fulltargetlist:
+            origk = k
             mc = ""
-            if k.startswith("mc:"):
+            if k.startswith("mc:") and k.count(':') >= 2:
                 mc = k.split(":")[1]
                 k = ":".join(k.split(":")[2:])
             ktask = task
@@ -635,6 +671,10 @@ class BBCooker:
                 k2 = k.split(":do_")
                 k = k2[0]
                 ktask = k2[1]
+
+            if mc not in self.multiconfigs:
+                 bb.fatal("Multiconfig dependency %s depends on nonexistent multiconfig configuration named %s" % (origk, mc))
+
             taskdata[mc].add_provider(localdata[mc], self.recipecaches[mc], k)
             current += 1
             if not ktask.startswith("do_"):
@@ -670,9 +710,9 @@ class BBCooker:
                         l = k.split(':')
                         depmc = l[2]
                         if depmc not in self.multiconfigs:
-                            bb.fatal("Multiconfig dependency %s depends on nonexistent mc configuration %s" % (k,depmc))
+                            bb.fatal("Multiconfig dependency %s depends on nonexistent multiconfig configuration named configuration %s" % (k,depmc))
                         else:
-                            logger.debug(1, "Adding providers for multiconfig dependency %s" % l[3])
+                            logger.debug("Adding providers for multiconfig dependency %s" % l[3])
                             taskdata[depmc].add_provider(localdata[depmc], self.recipecaches[depmc], l[3])
                             seen.add(k)
                             new = True
@@ -929,26 +969,33 @@ class BBCooker:
         logger.info("Task dependencies saved to 'task-depends.dot'")
 
     def show_appends_with_no_recipes(self):
+        appends_without_recipes = {}
         # Determine which bbappends haven't been applied
-
-        # First get list of recipes, including skipped
-        recipefns = list(self.recipecaches[''].pkg_fn.keys())
-        recipefns.extend(self.skiplist.keys())
-
-        # Work out list of bbappends that have been applied
-        applied_appends = []
-        for fn in recipefns:
-            applied_appends.extend(self.collection.get_file_appends(fn))
-
-        appends_without_recipes = []
-        for _, appendfn in self.collection.bbappends:
-            if not appendfn in applied_appends:
-                appends_without_recipes.append(appendfn)
-
-        if appends_without_recipes:
-            msg = 'No recipes available for:\n  %s' % '\n  '.join(appends_without_recipes)
-            warn_only = self.data.getVar("BB_DANGLINGAPPENDS_WARNONLY", \
-                 False) or "no"
+        for mc in self.multiconfigs:
+            # First get list of recipes, including skipped
+            recipefns = list(self.recipecaches[mc].pkg_fn.keys())
+            recipefns.extend(self.skiplist.keys())
+
+            # Work out list of bbappends that have been applied
+            applied_appends = []
+            for fn in recipefns:
+                applied_appends.extend(self.collections[mc].get_file_appends(fn))
+
+            appends_without_recipes[mc] = []
+            for _, appendfn in self.collections[mc].bbappends:
+                if not appendfn in applied_appends:
+                    appends_without_recipes[mc].append(appendfn)
+
+        msgs = []
+        for mc in sorted(appends_without_recipes.keys()):
+            if appends_without_recipes[mc]:
+                msgs.append('No recipes in %s available for:\n  %s' % (mc if mc else 'default',
+                                                                        '\n  '.join(appends_without_recipes[mc])))
+
+        if msgs:
+            msg = "\n".join(msgs)
+            warn_only = self.databuilder.mcdata[mc].getVar("BB_DANGLINGAPPENDS_WARNONLY", \
+                False) or "no"
             if warn_only.lower() in ("1", "yes", "true"):
                 bb.warn(msg)
             else:
@@ -1029,10 +1076,16 @@ class BBCooker:
         if pn in self.recipecaches[mc].providers:
             filenames = self.recipecaches[mc].providers[pn]
             eligible, foundUnique = bb.providers.filterProviders(filenames, pn, self.databuilder.mcdata[mc], self.recipecaches[mc])
-            filename = eligible[0]
+            if eligible is not None:
+                filename = eligible[0]
+            else:
+                filename = None
             return None, None, None, filename
         elif pn in self.recipecaches[mc].pkg_pn:
-            return bb.providers.findBestProvider(pn, self.databuilder.mcdata[mc], self.recipecaches[mc], self.recipecaches[mc].pkg_pn)
+            (latest, latest_f, preferred_ver, preferred_file, required) = bb.providers.findBestProvider(pn, self.databuilder.mcdata[mc], self.recipecaches[mc], self.recipecaches[mc].pkg_pn)
+            if required and preferred_file is None:
+                return None, None, None, None
+            return (latest, latest_f, preferred_ver, preferred_file)
         else:
             return None, None, None, None
 
@@ -1097,7 +1150,7 @@ class BBCooker:
             from bb import shell
         except ImportError:
             parselog.exception("Interactive mode not available")
-            sys.exit(1)
+            raise bb.BBHandledException()
         else:
             shell.start( self )
 
@@ -1249,15 +1302,15 @@ class BBCooker:
         if siggen_cache:
             bb.parse.siggen.checksum_cache.mtime_cache.clear()
 
-    def matchFiles(self, bf):
+    def matchFiles(self, bf, mc=''):
         """
         Find the .bb files which match the expression in 'buildfile'.
         """
         if bf.startswith("/") or bf.startswith("../"):
             bf = os.path.abspath(bf)
 
-        self.collection = CookerCollectFiles(self.bbfile_config_priorities)
-        filelist, masked, searchdirs = self.collection.collect_bbfiles(self.data, self.data)
+        self.collections = {mc: CookerCollectFiles(self.bbfile_config_priorities, mc)}
+        filelist, masked, searchdirs = self.collections[mc].collect_bbfiles(self.databuilder.mcdata[mc], self.databuilder.mcdata[mc])
         try:
             os.stat(bf)
             bf = os.path.abspath(bf)
@@ -1270,12 +1323,12 @@ class BBCooker:
                     matches.append(f)
             return matches
 
-    def matchFile(self, buildfile):
+    def matchFile(self, buildfile, mc=''):
         """
         Find the .bb file which matches the expression in 'buildfile'.
         Raise an error if multiple files
         """
-        matches = self.matchFiles(buildfile)
+        matches = self.matchFiles(buildfile, mc)
         if len(matches) != 1:
             if matches:
                 msg = "Unable to match '%s' to a specific recipe file - %s matches found:" % (buildfile, len(matches))
@@ -1316,14 +1369,14 @@ class BBCooker:
             task = "do_%s" % task
 
         fn, cls, mc = bb.cache.virtualfn2realfn(buildfile)
-        fn = self.matchFile(fn)
+        fn = self.matchFile(fn, mc)
 
         self.buildSetVars()
         self.reset_mtime_caches()
 
-        bb_cache = bb.cache.Cache(self.databuilder, self.data_hash, self.caches_array)
+        bb_caches = bb.cache.MulticonfigCache(self.databuilder, self.data_hash, self.caches_array)
 
-        infos = bb_cache.parse(fn, self.collection.get_file_appends(fn))
+        infos = bb_caches[mc].parse(fn, self.collections[mc].get_file_appends(fn))
         infos = dict(infos)
 
         fn = bb.cache.realfn2virtual(fn, cls, mc)
@@ -1411,7 +1464,7 @@ class BBCooker:
                 return True
             return retval
 
-        self.configuration.server_register_idlecallback(buildFileIdle, rq)
+        self.idleCallBackRegister(buildFileIdle, rq)
 
     def buildTargets(self, targets, task):
         """
@@ -1482,7 +1535,7 @@ class BBCooker:
         if 'universe' in targets:
             rq.rqdata.warn_multi_bb = True
 
-        self.configuration.server_register_idlecallback(buildTargetsIdle, rq)
+        self.idleCallBackRegister(buildTargetsIdle, rq)
 
 
     def getAllKeysWithFlags(self, flaglist):
@@ -1521,7 +1574,7 @@ class BBCooker:
         self.inotify_modified_files = []
 
         if not self.baseconfig_valid:
-            logger.debug(1, "Reloading base configuration data")
+            logger.debug("Reloading base configuration data")
             self.initConfigurationData()
             self.handlePRServ()
 
@@ -1533,6 +1586,7 @@ class BBCooker:
         if self.state in (state.shutdown, state.forceshutdown, state.error):
             if hasattr(self.parser, 'shutdown'):
                 self.parser.shutdown(clean=False, force = True)
+                self.parser.final_cleanup()
             raise bb.BBHandledException()
 
         if self.state != state.parsing:
@@ -1552,14 +1606,24 @@ class BBCooker:
                 for dep in self.configuration.extra_assume_provided:
                     self.recipecaches[mc].ignored_dependencies.add(dep)
 
-            self.collection = CookerCollectFiles(self.bbfile_config_priorities)
-            (filelist, masked, searchdirs) = self.collection.collect_bbfiles(self.data, self.data)
+            self.collections = {}
+
+            mcfilelist = {}
+            total_masked = 0
+            searchdirs = set()
+            for mc in self.multiconfigs:
+                self.collections[mc] = CookerCollectFiles(self.bbfile_config_priorities, mc)
+                (filelist, masked, search) = self.collections[mc].collect_bbfiles(self.databuilder.mcdata[mc], self.databuilder.mcdata[mc])
+
+                mcfilelist[mc] = filelist
+                total_masked += masked
+                searchdirs |= set(search)
 
             # Add inotify watches for directories searched for bb/bbappend files
             for dirent in searchdirs:
                 self.add_filewatch([[dirent]], dirs=True)
 
-            self.parser = CookerParser(self, filelist, masked)
+            self.parser = CookerParser(self, mcfilelist, total_masked)
             self.parsecache_valid = True
 
         self.state = state.parsing
@@ -1571,7 +1635,7 @@ class BBCooker:
             self.show_appends_with_no_recipes()
             self.handlePrefProviders()
             for mc in self.multiconfigs:
-                self.recipecaches[mc].bbfile_priority = self.collection.collection_priorities(self.recipecaches[mc].pkg_fn, self.data)
+                self.recipecaches[mc].bbfile_priority = self.collections[mc].collection_priorities(self.recipecaches[mc].pkg_fn, self.parser.mcfilelist[mc], self.data)
             self.state = state.running
 
             # Send an event listing all stamps reachable after parsing
@@ -1630,17 +1694,16 @@ class BBCooker:
         return pkgs_to_build
 
     def pre_serve(self):
-        # We now are in our own process so we can call this here.
-        # PRServ exits if its parent process exits
-        self.handlePRServ()
         return
 
     def post_serve(self):
+        self.shutdown(force=True)
         prserv.serv.auto_shutdown()
         if self.hashserv:
             self.hashserv.process.terminate()
             self.hashserv.process.join()
-        bb.event.fire(CookerExit(), self.data)
+        if hasattr(self, "data"):
+            bb.event.fire(CookerExit(), self.data)
 
     def shutdown(self, force = False):
         if force:
@@ -1650,6 +1713,7 @@ class BBCooker:
 
         if self.parser:
             self.parser.shutdown(clean=not force, force=force)
+            self.parser.final_cleanup()
 
     def finishcommand(self):
         self.state = state.initial
@@ -1663,8 +1727,9 @@ class BBCooker:
         self.finishcommand()
         self.extraconfigdata = {}
         self.command.reset()
-        self.databuilder.reset()
-        self.data = self.databuilder.data
+        if hasattr(self, "data"):
+           self.databuilder.reset()
+           self.data = self.databuilder.data
         self.parsecache_valid = False
         self.baseconfig_valid = False
 
@@ -1679,21 +1744,19 @@ class CookerExit(bb.event.Event):
 
 
 class CookerCollectFiles(object):
-    def __init__(self, priorities):
+    def __init__(self, priorities, mc=''):
+        self.mc = mc
         self.bbappends = []
         # Priorities is a list of tupples, with the second element as the pattern.
         # We need to sort the list with the longest pattern first, and so on to
         # the shortest.  This allows nested layers to be properly evaluated.
         self.bbfile_config_priorities = sorted(priorities, key=lambda tup: tup[1], reverse=True)
 
-    def calc_bbfile_priority( self, filename, matched = None ):
+    def calc_bbfile_priority(self, filename):
         for _, _, regex, pri in self.bbfile_config_priorities:
             if regex.match(filename):
-                if matched is not None:
-                    if not regex in matched:
-                        matched.add(regex)
-                return pri
-        return 0
+                return pri, regex
+        return 0, None
 
     def get_bbfiles(self):
         """Get list of default .bb files by reading out the current directory"""
@@ -1723,10 +1786,10 @@ class CookerCollectFiles(object):
         collectlog.debug(1, "collecting .bb files")
 
         files = (config.getVar( "BBFILES") or "").split()
-        config.setVar("BBFILES", " ".join(files))
 
         # Sort files by priority
-        files.sort( key=lambda fileitem: self.calc_bbfile_priority(fileitem) )
+        files.sort( key=lambda fileitem: self.calc_bbfile_priority(fileitem)[0] )
+        config.setVar("BBFILES_PRIORITIZED", " ".join(files))
 
         if not len(files):
             files = self.get_bbfiles()
@@ -1846,43 +1909,67 @@ class CookerCollectFiles(object):
             (bbappend, filename) = b
             if (bbappend == f) or ('%' in bbappend and bbappend.startswith(f[:bbappend.index('%')])):
                 filelist.append(filename)
-        return filelist
+        return tuple(filelist)
 
-    def collection_priorities(self, pkgfns, d):
+    def collection_priorities(self, pkgfns, fns, d):
+        # Return the priorities of the entries in pkgfns
+        # Also check that all the regexes in self.bbfile_config_priorities are used
+        # (but to do that we need to ensure skipped recipes aren't counted, nor
+        # collections in BBFILE_PATTERN_IGNORE_EMPTY)
 
         priorities = {}
+        seen = set()
+        matched = set()
+
+        matched_regex = set()
+        unmatched_regex = set()
+        for _, _, regex, _ in self.bbfile_config_priorities:
+            unmatched_regex.add(regex)
 
         # Calculate priorities for each file
-        matched = set()
         for p in pkgfns:
             realfn, cls, mc = bb.cache.virtualfn2realfn(p)
-            priorities[p] = self.calc_bbfile_priority(realfn, matched)
-
-        unmatched = set()
-        for _, _, regex, pri in self.bbfile_config_priorities:
-            if not regex in matched:
-                unmatched.add(regex)
-
-        # Don't show the warning if the BBFILE_PATTERN did match .bbappend files
-        def find_bbappend_match(regex):
+            priorities[p], regex = self.calc_bbfile_priority(realfn)
+            if regex in unmatched_regex:
+                matched_regex.add(regex)
+                unmatched_regex.remove(regex)
+            seen.add(realfn)
+            if regex:
+                matched.add(realfn)
+
+        if unmatched_regex:
+            # Account for bbappend files
             for b in self.bbappends:
                 (bbfile, append) = b
-                if regex.match(append):
-                    # If the bbappend is matched by already "matched set", return False
-                    for matched_regex in matched:
-                        if matched_regex.match(append):
-                            return False
-                    return True
-            return False
+                seen.add(append)
 
-        for unmatch in unmatched.copy():
-            if find_bbappend_match(unmatch):
-                unmatched.remove(unmatch)
+            # Account for skipped recipes
+            seen.update(fns)
+
+            seen.difference_update(matched)
+
+            def already_matched(fn):
+                for regex in matched_regex:
+                    if regex.match(fn):
+                        return True
+                return False
+
+            for unmatch in unmatched_regex.copy():
+                for fn in seen:
+                    if unmatch.match(fn):
+                        # If the bbappend or file was already matched by another regex, skip it
+                        # e.g. for a layer within a layer, the outer regex could match, the inner
+                        # regex may match nothing and we should warn about that
+                        if already_matched(fn):
+                            continue
+                        unmatched_regex.remove(unmatch)
+                        break
 
         for collection, pattern, regex, _ in self.bbfile_config_priorities:
-            if regex in unmatched:
+            if regex in unmatched_regex:
                 if d.getVar('BBFILE_PATTERN_IGNORE_EMPTY_%s' % collection) != '1':
-                    collectlog.warning("No bb files matched BBFILE_PATTERN_%s '%s'" % (collection, pattern))
+                    collectlog.warning("No bb files in %s matched BBFILE_PATTERN_%s '%s'" % (self.mc if self.mc else 'default',
+                                                                                             collection, pattern))
 
         return priorities
 
@@ -1931,7 +2018,8 @@ class Parser(multiprocessing.Process):
             except queue.Empty:
                 pass
             else:
-                self.results.cancel_join_thread()
+                self.results.close()
+                self.results.join_thread()
                 break
 
             if pending:
@@ -1940,6 +2028,8 @@ class Parser(multiprocessing.Process):
                 try:
                     job = self.jobs.pop()
                 except IndexError:
+                    self.results.close()
+                    self.results.join_thread()
                     break
                 result = self.parse(*job)
                 # Clear the siggen cache after parsing to control memory usage, its huge
@@ -1949,7 +2039,7 @@ class Parser(multiprocessing.Process):
             except queue.Full:
                 pending.append(result)
 
-    def parse(self, filename, appends):
+    def parse(self, mc, cache, filename, appends):
         try:
             origfilter = bb.event.LogHandler.filter
             # Record the filename we're parsing into any events generated
@@ -1963,7 +2053,7 @@ class Parser(multiprocessing.Process):
             bb.event.set_class_handlers(self.handlers.copy())
             bb.event.LogHandler.filter = parse_filter
 
-            return True, self.bb_cache.parse(filename, appends)
+            return True, mc, cache.parse(filename, appends)
         except Exception as exc:
             tb = sys.exc_info()[2]
             exc.recipe = filename
@@ -1978,8 +2068,8 @@ class Parser(multiprocessing.Process):
             bb.event.LogHandler.filter = origfilter
 
 class CookerParser(object):
-    def __init__(self, cooker, filelist, masked):
-        self.filelist = filelist
+    def __init__(self, cooker, mcfilelist, masked):
+        self.mcfilelist = mcfilelist
         self.cooker = cooker
         self.cfgdata = cooker.data
         self.cfghash = cooker.data_hash
@@ -1993,28 +2083,31 @@ class CookerParser(object):
 
         self.skipped = 0
         self.virtuals = 0
-        self.total = len(filelist)
 
         self.current = 0
         self.process_names = []
 
-        self.bb_cache = bb.cache.Cache(self.cfgbuilder, self.cfghash, cooker.caches_array)
-        self.fromcache = []
-        self.willparse = []
-        for filename in self.filelist:
-            appends = self.cooker.collection.get_file_appends(filename)
-            if not self.bb_cache.cacheValid(filename, appends):
-                self.willparse.append((filename, appends))
-            else:
-                self.fromcache.append((filename, appends))
-        self.toparse = self.total - len(self.fromcache)
+        self.bb_caches = bb.cache.MulticonfigCache(self.cfgbuilder, self.cfghash, cooker.caches_array)
+        self.fromcache = set()
+        self.willparse = set()
+        for mc in self.cooker.multiconfigs:
+            for filename in self.mcfilelist[mc]:
+                appends = self.cooker.collections[mc].get_file_appends(filename)
+                if not self.bb_caches[mc].cacheValid(filename, appends):
+                    self.willparse.add((mc, self.bb_caches[mc], filename, appends))
+                else:
+                    self.fromcache.add((mc, self.bb_caches[mc], filename, appends))
+
+        self.total = len(self.fromcache) + len(self.willparse)
+        self.toparse = len(self.willparse)
         self.progress_chunk = int(max(self.toparse / 100, 1))
 
         self.num_processes = min(int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS") or
-                                 multiprocessing.cpu_count()), len(self.willparse))
+                                 multiprocessing.cpu_count()), self.toparse)
 
         self.start()
         self.haveshutdown = False
+        self.syncthread = None
 
     def start(self):
         self.results = self.load_cached()
@@ -2022,7 +2115,9 @@ class CookerParser(object):
         if self.toparse:
             bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata)
             def init():
-                Parser.bb_cache = self.bb_cache
+                signal.signal(signal.SIGTERM, signal.SIG_DFL)
+                signal.signal(signal.SIGHUP, signal.SIG_DFL)
+                signal.signal(signal.SIGINT, signal.SIG_IGN)
                 bb.utils.set_process_name(multiprocessing.current_process().name)
                 multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, exitpriority=1)
                 multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, exitpriority=1)
@@ -2032,7 +2127,7 @@ class CookerParser(object):
 
             def chunkify(lst,n):
                 return [lst[i::n] for i in range(n)]
-            self.jobs = chunkify(self.willparse, self.num_processes)
+            self.jobs = chunkify(list(self.willparse), self.num_processes)
 
             for i in range(0, self.num_processes):
                 parser = Parser(self.jobs[i], self.result_queue, self.parser_quit, init, self.cooker.configuration.profile)
@@ -2056,12 +2151,9 @@ class CookerParser(object):
                                             self.total)
 
             bb.event.fire(event, self.cfgdata)
-            for process in self.processes:
-                self.parser_quit.put(None)
-        else:
-            self.parser_quit.cancel_join_thread()
-            for process in self.processes:
-                self.parser_quit.put(None)
+
+        for process in self.processes:
+            self.parser_quit.put(None)
 
         # Cleanup the queue before call process.join(), otherwise there might be
         # deadlocks.
@@ -2078,9 +2170,17 @@ class CookerParser(object):
             else:
                 process.join()
 
-        sync = threading.Thread(target=self.bb_cache.sync)
+        self.parser_quit.close()
+        # Allow data left in the cancel queue to be discarded
+        self.parser_quit.cancel_join_thread()
+
+        def sync_caches():
+            for c in self.bb_caches.values():
+                c.sync()
+
+        sync = threading.Thread(target=sync_caches, name="SyncThread")
+        self.syncthread = sync
         sync.start()
-        multiprocessing.util.Finalize(None, sync.join, exitpriority=-100)
         bb.codeparser.parser_cache_savemerge()
         bb.fetch.fetcher_parse_done()
         if self.cooker.configuration.profile:
@@ -2094,10 +2194,14 @@ class CookerParser(object):
             bb.utils.process_profilelog(profiles, pout = pout)
             print("Processed parsing statistics saved to %s" % (pout))
 
+    def final_cleanup(self):
+        if self.syncthread:
+            self.syncthread.join()
+
     def load_cached(self):
-        for filename, appends in self.fromcache:
-            cached, infos = self.bb_cache.load(filename, appends)
-            yield not cached, infos
+        for mc, cache, filename, appends in self.fromcache:
+            cached, infos = cache.load(filename, appends)
+            yield not cached, mc, infos
 
     def parse_generator(self):
         while True:
@@ -2119,25 +2223,25 @@ class CookerParser(object):
         result = []
         parsed = None
         try:
-            parsed, result = next(self.results)
+            parsed, mc, result = next(self.results)
         except StopIteration:
             self.shutdown()
             return False
         except bb.BBHandledException as exc:
             self.error += 1
             logger.error('Failed to parse recipe: %s' % exc.recipe)
-            self.shutdown(clean=False)
+            self.shutdown(clean=False, force=True)
             return False
         except ParsingFailure as exc:
             self.error += 1
             logger.error('Unable to parse %s: %s' %
                      (exc.recipe, bb.exceptions.to_string(exc.realexception)))
-            self.shutdown(clean=False)
+            self.shutdown(clean=False, force=True)
             return False
         except bb.parse.ParseError as exc:
             self.error += 1
             logger.error(str(exc))
-            self.shutdown(clean=False)
+            self.shutdown(clean=False, force=True)
             return False
         except bb.data_smart.ExpansionError as exc:
             self.error += 1
@@ -2146,7 +2250,7 @@ class CookerParser(object):
             tb = list(itertools.dropwhile(lambda e: e.filename.startswith(bbdir), exc.traceback))
             logger.error('ExpansionError during parsing %s', value.recipe,
                          exc_info=(etype, value, tb))
-            self.shutdown(clean=False)
+            self.shutdown(clean=False, force=True)
             return False
         except Exception as exc:
             self.error += 1
@@ -2158,7 +2262,7 @@ class CookerParser(object):
                 # Most likely, an exception occurred during raising an exception
                 import traceback
                 logger.error('Exception during parse: %s' % traceback.format_exc())
-            self.shutdown(clean=False)
+            self.shutdown(clean=False, force=True)
             return False
 
         self.current += 1
@@ -2175,13 +2279,16 @@ class CookerParser(object):
             if info_array[0].skipped:
                 self.skipped += 1
                 self.cooker.skiplist[virtualfn] = SkippedPackage(info_array[0])
-            (fn, cls, mc) = bb.cache.virtualfn2realfn(virtualfn)
-            self.bb_cache.add_info(virtualfn, info_array, self.cooker.recipecaches[mc],
+            self.bb_caches[mc].add_info(virtualfn, info_array, self.cooker.recipecaches[mc],
                                         parsed=parsed, watcher = self.cooker.add_filewatch)
         return True
 
     def reparse(self, filename):
-        infos = self.bb_cache.parse(filename, self.cooker.collection.get_file_appends(filename))
-        for vfn, info_array in infos:
-            (fn, cls, mc) = bb.cache.virtualfn2realfn(vfn)
-            self.cooker.recipecaches[mc].add_from_recipeinfo(vfn, info_array)
+        to_reparse = set()
+        for mc in self.cooker.multiconfigs:
+            to_reparse.add((mc, filename, self.cooker.collections[mc].get_file_appends(filename)))
+
+        for mc, filename, appends in to_reparse:
+            infos = self.bb_caches[mc].parse(filename, appends)
+            for vfn, info_array in infos:
+                self.cooker.recipecaches[mc].add_from_recipeinfo(vfn, info_array)
diff --git a/bitbake/lib/bb/cookerdata.py b/bitbake/lib/bb/cookerdata.py
index 472423fd..ba657c03 100644
--- a/bitbake/lib/bb/cookerdata.py
+++ b/bitbake/lib/bb/cookerdata.py
@@ -23,8 +23,8 @@ logger      = logging.getLogger("BitBake")
 parselog    = logging.getLogger("BitBake.Parsing")
 
 class ConfigParameters(object):
-    def __init__(self, argv=sys.argv):
-        self.options, targets = self.parseCommandLine(argv)
+    def __init__(self, argv=None):
+        self.options, targets = self.parseCommandLine(argv or sys.argv)
         self.environment = self.parseEnvironment()
 
         self.options.pkgs_to_build = targets or []
@@ -58,11 +58,18 @@ class ConfigParameters(object):
     def updateToServer(self, server, environment):
         options = {}
         for o in ["abort", "force", "invalidate_stamp",
-                  "verbose", "debug", "dry_run", "dump_signatures",
-                  "debug_domains", "extra_assume_provided", "profile",
-                  "prefile", "postfile", "server_timeout"]:
+                  "dry_run", "dump_signatures",
+                  "extra_assume_provided", "profile",
+                  "prefile", "postfile", "server_timeout",
+                  "nosetscene", "setsceneonly", "skipsetscene",
+                  "runall", "runonly", "writeeventlog"]:
             options[o] = getattr(self.options, o)
 
+        options['build_verbose_shell'] = self.options.verbose
+        options['build_verbose_stdout'] = self.options.verbose
+        options['default_loglevel'] = bb.msg.loggerDefaultLogLevel
+        options['debug_domains'] = bb.msg.loggerDefaultDomains
+
         ret, error = server.runCommand(["updateConfig", options, environment, sys.argv])
         if error:
             raise Exception("Unable to update the server configuration with local parameters: %s" % error)
@@ -111,11 +118,11 @@ class CookerConfiguration(object):
     """
 
     def __init__(self):
-        self.debug_domains = []
+        self.debug_domains = bb.msg.loggerDefaultDomains
+        self.default_loglevel = bb.msg.loggerDefaultLogLevel
         self.extra_assume_provided = []
         self.prefile = []
         self.postfile = []
-        self.debug = 0
         self.cmd = None
         self.abort = True
         self.force = False
@@ -125,34 +132,21 @@ class CookerConfiguration(object):
         self.skipsetscene = False
         self.invalidate_stamp = False
         self.dump_signatures = []
+        self.build_verbose_shell = False
+        self.build_verbose_stdout = False
         self.dry_run = False
         self.tracking = False
-        self.xmlrpcinterface = []
-        self.server_timeout = None
         self.writeeventlog = False
-        self.server_only = False
         self.limited_deps = False
         self.runall = []
         self.runonly = []
 
         self.env = {}
 
-    def setConfigParameters(self, parameters):
-        for key in self.__dict__.keys():
-            if key in parameters.options.__dict__:
-                setattr(self, key, parameters.options.__dict__[key])
-        self.env = parameters.environment.copy()
-
-    def setServerRegIdleCallback(self, srcb):
-        self.server_register_idlecallback = srcb
-
     def __getstate__(self):
         state = {}
         for key in self.__dict__.keys():
-            if key == "server_register_idlecallback":
-                state[key] = None
-            else:
-                state[key] = getattr(self, key)
+            state[key] = getattr(self, key)
         return state
 
     def __setstate__(self,state):
@@ -170,7 +164,7 @@ def catch_parse_error(func):
             import traceback
             parselog.critical(traceback.format_exc())
             parselog.critical("Unable to parse %s: %s" % (fn, exc))
-            sys.exit(1)
+            raise bb.BBHandledException()
         except bb.data_smart.ExpansionError as exc:
             import traceback
 
@@ -182,10 +176,10 @@ def catch_parse_error(func):
                 if not fn.startswith(bbdir):
                     break
             parselog.critical("Unable to parse %s" % fn, exc_info=(exc_class, exc, tb))
-            sys.exit(1)
+            raise bb.BBHandledException()
         except bb.parse.ParseError as exc:
             parselog.critical(str(exc))
-            sys.exit(1)
+            raise bb.BBHandledException()
     return wrapped
 
 @catch_parse_error
@@ -215,7 +209,7 @@ def findConfigFile(configfile, data):
     return None
 
 #
-# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working 
+# We search for a conf/bblayers.conf under an entry in BBPATH or in cwd working
 # up to /. If that fails, we search for a conf/bitbake.conf in BBPATH.
 #
 
@@ -297,6 +291,8 @@ class CookerDataBuilder(object):
 
             multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split()
             for config in multiconfig:
+                if config[0].isdigit():
+                    bb.fatal("Multiconfig name '%s' is invalid as multiconfigs cannot start with a digit" % config)
                 mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config)
                 bb.event.fire(bb.event.ConfigParsed(), mcdata)
                 self.mcdata[config] = mcdata
@@ -306,13 +302,13 @@ class CookerDataBuilder(object):
 
             self.data_hash = data_hash.hexdigest()
         except (SyntaxError, bb.BBHandledException):
-            raise bb.BBHandledException
+            raise bb.BBHandledException()
         except bb.data_smart.ExpansionError as e:
             logger.error(str(e))
-            raise bb.BBHandledException
+            raise bb.BBHandledException()
         except Exception:
             logger.exception("Error parsing configuration files")
-            raise bb.BBHandledException
+            raise bb.BBHandledException()
 
         # Create a copy so we can reset at a later date when UIs disconnect
         self.origdata = self.data
@@ -348,6 +344,9 @@ class CookerDataBuilder(object):
             layers = (data.getVar('BBLAYERS') or "").split()
             broken_layers = []
 
+            if not layers:
+                bb.fatal("The bblayers.conf file doesn't contain any BBLAYERS definition")
+
             data = bb.data.createCopy(data)
             approved = bb.utils.approved_variables()
 
@@ -361,7 +360,7 @@ class CookerDataBuilder(object):
                 for layer in broken_layers:
                     parselog.critical("   %s", layer)
                 parselog.critical("Please check BBLAYERS in %s" % (layerconf))
-                sys.exit(1)
+                raise bb.BBHandledException()
 
             for layer in layers:
                 parselog.debug(2, "Adding layer %s", layer)
@@ -387,10 +386,13 @@ class CookerDataBuilder(object):
                     invalid.append(entry)
                     continue
                 l, f = parts
-                if l in collections:
+                invert = l[0] == "!"
+                if invert:
+                    l = l[1:]
+                if (l in collections and not invert) or (l not in collections and invert):
                     data.appendVar("BBFILES", " " + f)
             if invalid:
-                bb.fatal("BBFILES_DYNAMIC entries must be of the form <collection name>:<filename pattern>, not:\n    %s" % "\n    ".join(invalid))
+                bb.fatal("BBFILES_DYNAMIC entries must be of the form {!}<collection name>:<filename pattern>, not:\n    %s" % "\n    ".join(invalid))
 
             layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split())
             collections_tmp = collections[:]
@@ -399,6 +401,8 @@ class CookerDataBuilder(object):
                 if c in collections_tmp:
                     bb.fatal("Found duplicated BBFILE_COLLECTIONS '%s', check bblayers.conf or layer.conf to fix it." % c)
                 compat = set((data.getVar("LAYERSERIES_COMPAT_%s" % c) or "").split())
+                if compat and not layerseries:
+                    bb.fatal("No core layer found to work with layer '%s'. Missing entry in bblayers.conf?" % c)
                 if compat and not (compat & layerseries):
                     bb.fatal("Layer %s is not compatible with the core layer which only supports these series: %s (layer is compatible with %s)"
                               % (c, " ".join(layerseries), " ".join(compat)))
@@ -430,9 +434,9 @@ class CookerDataBuilder(object):
             handlerfn = data.getVarFlag(var, "filename", False)
             if not handlerfn:
                 parselog.critical("Undefined event handler function '%s'" % var)
-                sys.exit(1)
+                raise bb.BBHandledException()
             handlerln = int(data.getVarFlag(var, "lineno", False))
-            bb.event.register(var, data.getVar(var, False),  (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln)
+            bb.event.register(var, data.getVar(var, False),  (data.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data)
 
         data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))
 
diff --git a/bitbake/lib/bb/daemonize.py b/bitbake/lib/bb/daemonize.py
index f01e6ec7..c187fcfc 100644
--- a/bitbake/lib/bb/daemonize.py
+++ b/bitbake/lib/bb/daemonize.py
@@ -14,6 +14,8 @@ import sys
 import io
 import traceback
 
+import bb
+
 def createDaemon(function, logfile):
     """
     Detach a process from the controlling terminal and run it in the
diff --git a/bitbake/lib/bb/data.py b/bitbake/lib/bb/data.py
index b0683c51..97022853 100644
--- a/bitbake/lib/bb/data.py
+++ b/bitbake/lib/bb/data.py
@@ -161,6 +161,12 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
         return True
 
     if func:
+        # Write a comment indicating where the shell function came from (line number and filename) to make it easier
+        # for the user to diagnose task failures. This comment is also used by build.py to determine the metadata
+        # location of shell functions.
+        o.write("# line: {0}, file: {1}\n".format(
+            d.getVarFlag(var, "lineno", False),
+            d.getVarFlag(var, "filename", False)))
         # NOTE: should probably check for unbalanced {} within the var
         val = val.rstrip('\n')
         o.write("%s() {\n%s\n}\n" % (varExpanded, val))
diff --git a/bitbake/lib/bb/data_smart.py b/bitbake/lib/bb/data_smart.py
index 7f1b6dcb..8291ca65 100644
--- a/bitbake/lib/bb/data_smart.py
+++ b/bitbake/lib/bb/data_smart.py
@@ -28,7 +28,7 @@ logger = logging.getLogger("BitBake.Data")
 
 __setvar_keyword__ = ["_append", "_prepend", "_remove"]
 __setvar_regexp__ = re.compile(r'(?P<base>.*?)(?P<keyword>_append|_prepend|_remove)(_(?P<add>[^A-Z]*))?$')
-__expand_var_regexp__ = re.compile(r"\${[a-zA-Z0-9\-_+./~]+?}")
+__expand_var_regexp__ = re.compile(r"\${[a-zA-Z0-9\-_+./~:]+?}")
 __expand_python_regexp__ = re.compile(r"\${@.+?}")
 __whitespace_split__ = re.compile(r'(\s)')
 __override_regexp__ = re.compile(r'[a-z0-9]+')
@@ -189,7 +189,7 @@ class IncludeHistory(object):
         if self.current.parent:
             self.current = self.current.parent
         else:
-            bb.warn("Include log: Tried to finish '%s' at top level." % filename)
+            bb.warn("Include log: Tried to finish '%s' at top level." % self.filename)
         return False
 
     def emit(self, o, level = 0):
@@ -411,6 +411,8 @@ class DataSmart(MutableMapping):
                 raise
             except bb.parse.SkipRecipe:
                 raise
+            except bb.BBHandledException:
+                raise
             except Exception as exc:
                 tb = sys.exc_info()[2]
                 raise ExpansionError(varname, s, exc).with_traceback(tb) from exc
@@ -481,6 +483,7 @@ class DataSmart(MutableMapping):
 
     def setVar(self, var, value, **loginfo):
         #print("var=" + str(var) + "  val=" + str(value))
+        var = var.replace(":", "_")
         self.expand_cache = {}
         parsing=False
         if 'parsing' in loginfo:
@@ -589,6 +592,8 @@ class DataSmart(MutableMapping):
         """
         Rename the variable key to newkey
         """
+        key = key.replace(":", "_")
+        newkey = newkey.replace(":", "_")
         if key == newkey:
             bb.warn("Calling renameVar with equivalent keys (%s) is invalid" % key)
             return
@@ -637,6 +642,7 @@ class DataSmart(MutableMapping):
         self.setVar(var + "_prepend", value, ignore=True, parsing=True)
 
     def delVar(self, var, **loginfo):
+        var = var.replace(":", "_")
         self.expand_cache = {}
 
         loginfo['detail'] = ""
@@ -664,6 +670,7 @@ class DataSmart(MutableMapping):
                          override = None
 
     def setVarFlag(self, var, flag, value, **loginfo):
+        var = var.replace(":", "_")
         self.expand_cache = {}
 
         if 'op' not in loginfo:
@@ -687,6 +694,7 @@ class DataSmart(MutableMapping):
             self.dict["__exportlist"]["_content"].add(var)
 
     def getVarFlag(self, var, flag, expand=True, noweakdefault=False, parsing=False, retparser=False):
+        var = var.replace(":", "_")
         if flag == "_content":
             cachename = var
         else:
@@ -814,6 +822,7 @@ class DataSmart(MutableMapping):
         return value
 
     def delVarFlag(self, var, flag, **loginfo):
+        var = var.replace(":", "_")
         self.expand_cache = {}
 
         local_var, _ = self._findVar(var)
@@ -831,6 +840,7 @@ class DataSmart(MutableMapping):
             del self.dict[var][flag]
 
     def appendVarFlag(self, var, flag, value, **loginfo):
+        var = var.replace(":", "_")
         loginfo['op'] = 'append'
         loginfo['flag'] = flag
         self.varhistory.record(**loginfo)
@@ -838,6 +848,7 @@ class DataSmart(MutableMapping):
         self.setVarFlag(var, flag, newvalue, ignore=True)
 
     def prependVarFlag(self, var, flag, value, **loginfo):
+        var = var.replace(":", "_")
         loginfo['op'] = 'prepend'
         loginfo['flag'] = flag
         self.varhistory.record(**loginfo)
@@ -845,6 +856,7 @@ class DataSmart(MutableMapping):
         self.setVarFlag(var, flag, newvalue, ignore=True)
 
     def setVarFlags(self, var, flags, **loginfo):
+        var = var.replace(":", "_")
         self.expand_cache = {}
         infer_caller_details(loginfo)
         if not var in self.dict:
@@ -859,6 +871,7 @@ class DataSmart(MutableMapping):
             self.dict[var][i] = flags[i]
 
     def getVarFlags(self, var, expand = False, internalflags=False):
+        var = var.replace(":", "_")
         local_var, _ = self._findVar(var)
         flags = {}
 
@@ -875,6 +888,7 @@ class DataSmart(MutableMapping):
 
 
     def delVarFlags(self, var, **loginfo):
+        var = var.replace(":", "_")
         self.expand_cache = {}
         if not var in self.dict:
             self._makeShadowCopy(var)
@@ -1005,7 +1019,7 @@ class DataSmart(MutableMapping):
             else:
                 data.update({key:value})
 
-            varflags = d.getVarFlags(key, internalflags = True)
+            varflags = d.getVarFlags(key, internalflags = True, expand=["vardepvalue"])
             if not varflags:
                 continue
             for f in varflags:
diff --git a/bitbake/lib/bb/event.py b/bitbake/lib/bb/event.py
index d1359f01..0454c753 100644
--- a/bitbake/lib/bb/event.py
+++ b/bitbake/lib/bb/event.py
@@ -10,17 +10,17 @@ BitBake build tools.
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
-import sys
-import pickle
-import logging
-import atexit
-import traceback
 import ast
+import atexit
+import collections
+import logging
+import pickle
+import sys
 import threading
+import traceback
 
-import bb.utils
-import bb.compat
 import bb.exceptions
+import bb.utils
 
 # This is the pid for which we should generate the event. This is set when
 # the runqueue forks off.
@@ -56,7 +56,7 @@ def set_class_handlers(h):
     _handlers = h
 
 def clean_class_handlers():
-    return bb.compat.OrderedDict()
+    return collections.OrderedDict()
 
 # Internal
 _handlers = clean_class_handlers()
@@ -118,6 +118,8 @@ def fire_class_handlers(event, d):
             if _eventfilter:
                 if not _eventfilter(name, handler, event, d):
                     continue
+            if d is not None and not name in (d.getVar("__BBHANDLERS_MC") or set()):
+                continue
             execute_handler(name, handler, event, d)
 
 ui_queue = []
@@ -227,11 +229,19 @@ def fire_from_worker(event, d):
     fire_ui_handlers(event, d)
 
 noop = lambda _: None
-def register(name, handler, mask=None, filename=None, lineno=None):
+def register(name, handler, mask=None, filename=None, lineno=None, data=None):
     """Register an Event handler"""
 
+    if data is not None and data.getVar("BB_CURRENT_MC"):
+        mc = data.getVar("BB_CURRENT_MC")
+        name = '%s%s' % (mc.replace('-', '_'), name)
+
     # already registered
     if name in _handlers:
+        if data is not None:
+            bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
+            bbhands_mc.add(name)
+            data.setVar("__BBHANDLERS_MC", bbhands_mc)
         return AlreadyRegistered
 
     if handler is not None:
@@ -268,10 +278,20 @@ def register(name, handler, mask=None, filename=None, lineno=None):
                     _event_handler_map[m] = {}
                 _event_handler_map[m][name] = True
 
+        if data is not None:
+            bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
+            bbhands_mc.add(name)
+            data.setVar("__BBHANDLERS_MC", bbhands_mc)
+
         return Registered
 
-def remove(name, handler):
+def remove(name, handler, data=None):
     """Remove an Event handler"""
+    if data is not None:
+        if data.getVar("BB_CURRENT_MC"):
+            mc = data.getVar("BB_CURRENT_MC")
+            name = '%s%s' % (mc.replace('-', '_'), name)
+
     _handlers.pop(name)
     if name in _catchall_handlers:
         _catchall_handlers.pop(name)
@@ -279,6 +299,12 @@ def remove(name, handler):
         if name in _event_handler_map[event]:
             _event_handler_map[event].pop(name)
 
+    if data is not None:
+        bbhands_mc = (data.getVar("__BBHANDLERS_MC") or set())
+        if name in bbhands_mc:
+            bbhands_mc.remove(name)
+            data.setVar("__BBHANDLERS_MC", bbhands_mc)
+
 def get_handlers():
     return _handlers
 
@@ -389,6 +415,10 @@ class RecipeEvent(Event):
 class RecipePreFinalise(RecipeEvent):
     """ Recipe Parsing Complete but not yet finalised"""
 
+class RecipePostKeyExpansion(RecipeEvent):
+    """ Recipe Parsing Complete but not yet finalised"""
+
+
 class RecipeTaskPreProcess(RecipeEvent):
     """
     Recipe Tasks about to be finalised
@@ -640,6 +670,17 @@ class ReachableStamps(Event):
         Event.__init__(self)
         self.stamps = stamps
 
+class StaleSetSceneTasks(Event):
+    """
+    An event listing setscene tasks which are 'stale' and will
+    be rerun. The metadata may use to clean up stale data.
+    tasks is a mapping of tasks and matching stale stamps.
+    """
+
+    def __init__(self, tasks):
+        Event.__init__(self)
+        self.tasks = tasks
+
 class FilesMatchingFound(Event):
     """
     Event when a list of files matching the supplied pattern has
diff --git a/bitbake/lib/bb/fetch2/__init__.py b/bitbake/lib/bb/fetch2/__init__.py
index eb112f06..dbf8b50e 100644
--- a/bitbake/lib/bb/fetch2/__init__.py
+++ b/bitbake/lib/bb/fetch2/__init__.py
@@ -290,7 +290,7 @@ class URI(object):
 
     def _param_str_split(self, string, elmdelim, kvdelim="="):
         ret = collections.OrderedDict()
-        for k, v in [x.split(kvdelim, 1) for x in string.split(elmdelim)]:
+        for k, v in [x.split(kvdelim, 1) for x in string.split(elmdelim) if x]:
             ret[k] = v
         return ret
 
@@ -428,7 +428,7 @@ def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
     uri_decoded = list(decodeurl(ud.url))
     uri_find_decoded = list(decodeurl(uri_find))
     uri_replace_decoded = list(decodeurl(uri_replace))
-    logger.debug(2, "For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
+    logger.debug2("For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
     result_decoded = ['', '', '', '', '', {}]
     for loc, i in enumerate(uri_find_decoded):
         result_decoded[loc] = uri_decoded[loc]
@@ -474,7 +474,7 @@ def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
     result = encodeurl(result_decoded)
     if result == ud.url:
         return None
-    logger.debug(2, "For url %s returning %s" % (ud.url, result))
+    logger.debug2("For url %s returning %s" % (ud.url, result))
     return result
 
 methods = []
@@ -499,9 +499,9 @@ def fetcher_init(d):
     # When to drop SCM head revisions controlled by user policy
     srcrev_policy = d.getVar('BB_SRCREV_POLICY') or "clear"
     if srcrev_policy == "cache":
-        logger.debug(1, "Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
+        logger.debug("Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
     elif srcrev_policy == "clear":
-        logger.debug(1, "Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
+        logger.debug("Clearing SRCREV cache due to cache policy of: %s", srcrev_policy)
         revs.clear()
     else:
         raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
@@ -562,6 +562,9 @@ def verify_checksum(ud, d, precomputed={}):
 
         checksum_expected = getattr(ud, "%s_expected" % checksum_id)
 
+        if checksum_expected == '':
+            checksum_expected = None
+
         return {
             "id": checksum_id,
             "name": checksum_name,
@@ -612,7 +615,7 @@ def verify_checksum(ud, d, precomputed={}):
 
     for ci in checksum_infos:
         if ci["expected"] and ci["expected"] != ci["data"]:
-            messages.append("File: '%s' has %s checksum %s when %s was " \
+            messages.append("File: '%s' has %s checksum '%s' when '%s' was " \
                             "expected" % (ud.localpath, ci["id"], ci["data"], ci["expected"]))
             bad_checksum = ci["data"]
 
@@ -853,18 +856,13 @@ def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
         if val:
             cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
 
-    # Ensure that a _PYTHON_SYSCONFIGDATA_NAME value set by a recipe
-    # (for example via python3native.bbclass since warrior) is not set for
-    # host Python (otherwise tools like git-make-shallow will fail)
-    cmd = 'unset _PYTHON_SYSCONFIGDATA_NAME; ' + cmd
-
     # Disable pseudo as it may affect ssh, potentially causing it to hang.
     cmd = 'export PSEUDO_DISABLED=1; ' + cmd
 
     if workdir:
-        logger.debug(1, "Running '%s' in %s" % (cmd, workdir))
+        logger.debug("Running '%s' in %s" % (cmd, workdir))
     else:
-        logger.debug(1, "Running %s", cmd)
+        logger.debug("Running %s", cmd)
 
     success = False
     error_message = ""
@@ -873,7 +871,7 @@ def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
         (output, errors) = bb.process.run(cmd, log=log, shell=True, stderr=subprocess.PIPE, cwd=workdir)
         success = True
     except bb.process.NotFoundError as e:
-        error_message = "Fetch command %s" % (e.command)
+        error_message = "Fetch command %s not found" % (e.command)
     except bb.process.ExecutionError as e:
         if e.stdout:
             output = "output:\n%s\n%s" % (e.stdout, e.stderr)
@@ -905,7 +903,7 @@ def check_network_access(d, info, url):
     elif not trusted_network(d, url):
         raise UntrustedUrl(url, info)
     else:
-        logger.debug(1, "Fetcher accessed the network with the command %s" % info)
+        logger.debug("Fetcher accessed the network with the command %s" % info)
 
 def build_mirroruris(origud, mirrors, ld):
     uris = []
@@ -931,7 +929,7 @@ def build_mirroruris(origud, mirrors, ld):
                     continue
 
                 if not trusted_network(ld, newuri):
-                    logger.debug(1, "Mirror %s not in the list of trusted networks, skipping" %  (newuri))
+                    logger.debug("Mirror %s not in the list of trusted networks, skipping" %  (newuri))
                     continue
 
                 # Create a local copy of the mirrors minus the current line
@@ -944,8 +942,8 @@ def build_mirroruris(origud, mirrors, ld):
                     newud = FetchData(newuri, ld)
                     newud.setup_localpath(ld)
                 except bb.fetch2.BBFetchException as e:
-                    logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
-                    logger.debug(1, str(e))
+                    logger.debug("Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
+                    logger.debug(str(e))
                     try:
                         # setup_localpath of file:// urls may fail, we should still see
                         # if mirrors of the url exist
@@ -1048,8 +1046,8 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
         elif isinstance(e, NoChecksumError):
             raise
         else:
-            logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (ud.url, origud.url))
-            logger.debug(1, str(e))
+            logger.debug("Mirror fetch failure for url %s (original url: %s)" % (ud.url, origud.url))
+            logger.debug(str(e))
         try:
             ud.method.clean(ud, ld)
         except UnboundLocalError:
@@ -1195,8 +1193,6 @@ def get_checksum_file_list(d):
             paths = ud.method.localpaths(ud, d)
             for f in paths:
                 pth = ud.decodedurl
-                if '*' in pth:
-                    f = os.path.join(os.path.abspath(f), pth)
                 if f.startswith(dl_dir):
                     # The local fetcher's behaviour is to return a path under DL_DIR if it couldn't find the file anywhere else
                     if os.path.exists(f):
@@ -1250,7 +1246,7 @@ class FetchData(object):
 
             if checksum_name in self.parm:
                 checksum_expected = self.parm[checksum_name]
-            elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3"]:
+            elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3", "az"]:
                 checksum_expected = None
             else:
                 checksum_expected = d.getVarFlag("SRC_URI", checksum_name)
@@ -1365,9 +1361,6 @@ class FetchMethod(object):
         # We cannot compute checksums for directories
         if os.path.isdir(urldata.localpath):
             return False
-        if urldata.localpath.find("*") != -1:
-            return False
-
         return True
 
     def recommends_checksum(self, urldata):
@@ -1430,11 +1423,6 @@ class FetchMethod(object):
         iterate = False
         file = urldata.localpath
 
-        # Localpath can't deal with 'dir/*' entries, so it converts them to '.',
-        # but it must be corrected back for local files copying
-        if urldata.basename == '*' and file.endswith('/.'):
-            file = '%s/%s' % (file.rstrip('/.'), urldata.path)
-
         try:
             unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
         except ValueError as exc:
@@ -1471,6 +1459,10 @@ class FetchMethod(object):
                 cmd = '7z x -so %s | tar x --no-same-owner -f -' % file
             elif file.endswith('.7z'):
                 cmd = '7za x -y %s 1>/dev/null' % file
+            elif file.endswith('.tzst') or file.endswith('.tar.zst'):
+                cmd = 'zstd --decompress --stdout %s | tar x --no-same-owner -f -' % file
+            elif file.endswith('.zst'):
+                cmd = 'zstd --decompress --stdout %s > %s' % (file, efile)
             elif file.endswith('.zip') or file.endswith('.jar'):
                 try:
                     dos = bb.utils.to_boolean(urldata.parm.get('dos'), False)
@@ -1530,7 +1522,7 @@ class FetchMethod(object):
                     if urlpath.find("/") != -1:
                         destdir = urlpath.rsplit("/", 1)[0] + '/'
                         bb.utils.mkdirhier("%s/%s" % (unpackdir, destdir))
-                cmd = 'cp -fpPRH %s %s' % (file, destdir)
+                cmd = 'cp -fpPRH "%s" "%s"' % (file, destdir)
 
         if not cmd:
             return
@@ -1613,10 +1605,15 @@ class FetchMethod(object):
         """
         if os.path.exists(ud.localpath):
             return True
-        if ud.localpath.find("*") != -1:
-            return True
         return False
 
+    def implicit_urldata(self, ud, d):
+        """
+        Get a list of FetchData objects for any implicit URLs that will also
+        be downloaded when we fetch the given URL.
+        """
+        return []
+
 class Fetch(object):
     def __init__(self, urls, d, cache = True, localonly = False, connection_cache = None):
         if localonly and cache:
@@ -1694,7 +1691,7 @@ class Fetch(object):
                 if m.verify_donestamp(ud, self.d) and not m.need_update(ud, self.d):
                     done = True
                 elif m.try_premirror(ud, self.d):
-                    logger.debug(1, "Trying PREMIRRORS")
+                    logger.debug("Trying PREMIRRORS")
                     mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
                     done = m.try_mirrors(self, ud, self.d, mirrors)
                     if done:
@@ -1704,7 +1701,7 @@ class Fetch(object):
                             m.update_donestamp(ud, self.d)
                         except ChecksumError as e:
                             logger.warning("Checksum failure encountered with premirror download of %s - will attempt other sources." % u)
-                            logger.debug(1, str(e))
+                            logger.debug(str(e))
                             done = False
 
                 if premirroronly:
@@ -1716,7 +1713,7 @@ class Fetch(object):
                     try:
                         if not trusted_network(self.d, ud.url):
                             raise UntrustedUrl(ud.url)
-                        logger.debug(1, "Trying Upstream")
+                        logger.debug("Trying Upstream")
                         m.download(ud, self.d)
                         if hasattr(m, "build_mirror_data"):
                             m.build_mirror_data(ud, self.d)
@@ -1731,19 +1728,19 @@ class Fetch(object):
                     except BBFetchException as e:
                         if isinstance(e, ChecksumError):
                             logger.warning("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
-                            logger.debug(1, str(e))
+                            logger.debug(str(e))
                             if os.path.exists(ud.localpath):
                                 rename_bad_checksum(ud, e.checksum)
                         elif isinstance(e, NoChecksumError):
                             raise
                         else:
                             logger.warning('Failed to fetch URL %s, attempting MIRRORS if available' % u)
-                            logger.debug(1, str(e))
+                            logger.debug(str(e))
                         firsterr = e
                         # Remove any incomplete fetch
                         if not verified_stamp:
                             m.clean(ud, self.d)
-                        logger.debug(1, "Trying MIRRORS")
+                        logger.debug("Trying MIRRORS")
                         mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
                         done = m.try_mirrors(self, ud, self.d, mirrors)
 
@@ -1780,7 +1777,7 @@ class Fetch(object):
             ud = self.ud[u]
             ud.setup_localpath(self.d)
             m = ud.method
-            logger.debug(1, "Testing URL %s", u)
+            logger.debug("Testing URL %s", u)
             # First try checking uri, u, from PREMIRRORS
             mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
             ret = m.try_mirrors(self, ud, self.d, mirrors, True)
@@ -1842,6 +1839,24 @@ class Fetch(object):
             if ud.lockfile:
                 bb.utils.unlockfile(lf)
 
+    def expanded_urldata(self, urls=None):
+        """
+        Get an expanded list of FetchData objects covering both the given
+        URLS and any additional implicit URLs that are added automatically by
+        the appropriate FetchMethod.
+        """
+
+        if not urls:
+            urls = self.urls
+
+        urldata = []
+        for url in urls:
+            ud = self.ud[url]
+            urldata.append(ud)
+            urldata += ud.method.implicit_urldata(ud, self.d)
+
+        return urldata
+
 class FetchConnectionCache(object):
     """
         A class which represents an container for socket connections.
@@ -1896,6 +1911,7 @@ from . import repo
 from . import clearcase
 from . import npm
 from . import npmsw
+from . import az
 
 methods.append(local.Local())
 methods.append(wget.Wget())
@@ -1915,3 +1931,4 @@ methods.append(repo.Repo())
 methods.append(clearcase.ClearCase())
 methods.append(npm.Npm())
 methods.append(npmsw.NpmShrinkWrap())
+methods.append(az.Az())
diff --git a/bitbake/lib/bb/fetch2/az.py b/bitbake/lib/bb/fetch2/az.py
new file mode 100644
index 00000000..3ccc594c
--- /dev/null
+++ b/bitbake/lib/bb/fetch2/az.py
@@ -0,0 +1,93 @@
+"""
+BitBake 'Fetch' Azure Storage implementation
+
+"""
+
+# Copyright (C) 2021 Alejandro Hernandez Samaniego
+#
+# Based on bb.fetch2.wget:
+# Copyright (C) 2003, 2004  Chris Larson
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Based on functions from the base bb module, Copyright 2003 Holger Schurig
+
+import shlex
+import os
+import bb
+from   bb.fetch2 import FetchError
+from   bb.fetch2 import logger
+from   bb.fetch2.wget import Wget
+
+
+class Az(Wget):
+
+    def supports(self, ud, d):
+        """
+        Check to see if a given url can be fetched from Azure Storage
+        """
+        return ud.type in ['az']
+
+
+    def checkstatus(self, fetch, ud, d, try_again=True):
+
+        # checkstatus discards parameters either way, we need to do this before adding the SAS
+        ud.url = ud.url.replace('az://','https://').split(';')[0]
+
+        az_sas = d.getVar('AZ_SAS')
+        if az_sas and az_sas not in ud.url:
+            ud.url += az_sas
+
+        return Wget.checkstatus(self, fetch, ud, d, try_again)
+
+    # Override download method, include retries
+    def download(self, ud, d, retries=3):
+        """Fetch urls"""
+
+        # If were reaching the account transaction limit we might be refused a connection,
+        # retrying allows us to avoid false negatives since the limit changes over time
+        fetchcmd = self.basecmd + ' --retry-connrefused --waitretry=5'
+
+        # We need to provide a localpath to avoid wget using the SAS
+        # ud.localfile either has the downloadfilename or ud.path
+        localpath = os.path.join(d.getVar("DL_DIR"), ud.localfile)
+        bb.utils.mkdirhier(os.path.dirname(localpath))
+        fetchcmd += " -O %s" % shlex.quote(localpath)
+
+
+        if ud.user and ud.pswd:
+            fetchcmd += " --user=%s --password=%s --auth-no-challenge" % (ud.user, ud.pswd)
+
+        # Check if a Shared Access Signature was given and use it
+        az_sas = d.getVar('AZ_SAS')
+
+        if az_sas:
+            azuri = '%s%s%s%s' % ('https://', ud.host, ud.path, az_sas)
+        else:
+            azuri = '%s%s%s' % ('https://', ud.host, ud.path)
+
+        if os.path.exists(ud.localpath):
+            # file exists, but we didnt complete it.. trying again.
+            fetchcmd += d.expand(" -c -P ${DL_DIR} '%s'" % azuri)
+        else:
+            fetchcmd += d.expand(" -P ${DL_DIR} '%s'" % azuri)
+
+        try:
+            self._runwget(ud, d, fetchcmd, False)
+        except FetchError as e:
+            # Azure fails on handshake sometimes when using wget after some stress, producing a
+            # FetchError from the fetcher, if the artifact exists retyring should succeed
+            if 'Unable to establish SSL connection' in str(e):
+                logger.debug2('Unable to establish SSL connection: Retries remaining: %s, Retrying...' % retries)
+                self.download(ud, d, retries -1)
+
+        # Sanity check since wget can pretend it succeed when it didn't
+        # Also, this used to happen if sourceforge sent us to the mirror page
+        if not os.path.exists(ud.localpath):
+            raise FetchError("The fetch command returned success for url %s but %s doesn't exist?!" % (azuri, ud.localpath), azuri)
+
+        if os.path.getsize(ud.localpath) == 0:
+            os.remove(ud.localpath)
+            raise FetchError("The fetch of %s resulted in a zero size file?! Deleting and failing since this isn't right." % (azuri), azuri)
+
+        return True
diff --git a/bitbake/lib/bb/fetch2/bzr.py b/bitbake/lib/bb/fetch2/bzr.py
index 566ace9f..fc558f50 100644
--- a/bitbake/lib/bb/fetch2/bzr.py
+++ b/bitbake/lib/bb/fetch2/bzr.py
@@ -74,16 +74,16 @@ class Bzr(FetchMethod):
 
         if os.access(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir), '.bzr'), os.R_OK):
             bzrcmd = self._buildbzrcommand(ud, d, "update")
-            logger.debug(1, "BZR Update %s", ud.url)
+            logger.debug("BZR Update %s", ud.url)
             bb.fetch2.check_network_access(d, bzrcmd, ud.url)
             runfetchcmd(bzrcmd, d, workdir=os.path.join(ud.pkgdir, os.path.basename(ud.path)))
         else:
             bb.utils.remove(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir)), True)
             bzrcmd = self._buildbzrcommand(ud, d, "fetch")
             bb.fetch2.check_network_access(d, bzrcmd, ud.url)
-            logger.debug(1, "BZR Checkout %s", ud.url)
+            logger.debug("BZR Checkout %s", ud.url)
             bb.utils.mkdirhier(ud.pkgdir)
-            logger.debug(1, "Running %s", bzrcmd)
+            logger.debug("Running %s", bzrcmd)
             runfetchcmd(bzrcmd, d, workdir=ud.pkgdir)
 
         scmdata = ud.parm.get("scmdata", "")
@@ -109,7 +109,7 @@ class Bzr(FetchMethod):
         """
         Return the latest upstream revision number
         """
-        logger.debug(2, "BZR fetcher hitting network for %s", ud.url)
+        logger.debug2("BZR fetcher hitting network for %s", ud.url)
 
         bb.fetch2.check_network_access(d, self._buildbzrcommand(ud, d, "revno"), ud.url)
 
diff --git a/bitbake/lib/bb/fetch2/clearcase.py b/bitbake/lib/bb/fetch2/clearcase.py
index 49d7ae1b..1a9c8637 100644
--- a/bitbake/lib/bb/fetch2/clearcase.py
+++ b/bitbake/lib/bb/fetch2/clearcase.py
@@ -70,7 +70,7 @@ class ClearCase(FetchMethod):
         return ud.type in ['ccrc']
 
     def debug(self, msg):
-        logger.debug(1, "ClearCase: %s", msg)
+        logger.debug("ClearCase: %s", msg)
 
     def urldata_init(self, ud, d):
         """
diff --git a/bitbake/lib/bb/fetch2/cvs.py b/bitbake/lib/bb/fetch2/cvs.py
index 29123a48..01de5ff4 100644
--- a/bitbake/lib/bb/fetch2/cvs.py
+++ b/bitbake/lib/bb/fetch2/cvs.py
@@ -51,6 +51,10 @@ class Cvs(FetchMethod):
 
         ud.localfile = d.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath))
 
+        pkg = d.getVar('PN')
+        cvsdir = d.getVar("CVSDIR") or (d.getVar("DL_DIR") + "/cvs")
+        ud.pkgdir = os.path.join(cvsdir, pkg)
+
     def need_update(self, ud, d):
         if (ud.date == "now"):
             return True
@@ -105,11 +109,8 @@ class Cvs(FetchMethod):
             cvsupdatecmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvsupdatecmd)
 
         # create module directory
-        logger.debug(2, "Fetch: checking for module directory")
-        pkg = d.getVar('PN')
-        cvsdir = d.getVar("CVSDIR") or (d.getVar("DL_DIR") + "/cvs")
-        pkgdir = os.path.join(cvsdir, pkg)
-        moddir = os.path.join(pkgdir, localdir)
+        logger.debug2("Fetch: checking for module directory")
+        moddir = os.path.join(ud.pkgdir, localdir)
         workdir = None
         if os.access(os.path.join(moddir, 'CVS'), os.R_OK):
             logger.info("Update " + ud.url)
@@ -120,9 +121,9 @@ class Cvs(FetchMethod):
         else:
             logger.info("Fetch " + ud.url)
             # check out sources there
-            bb.utils.mkdirhier(pkgdir)
-            workdir = pkgdir
-            logger.debug(1, "Running %s", cvscmd)
+            bb.utils.mkdirhier(ud.pkgdir)
+            workdir = ud.pkgdir
+            logger.debug("Running %s", cvscmd)
             bb.fetch2.check_network_access(d, cvscmd, ud.url)
             cmd = cvscmd
 
@@ -140,7 +141,7 @@ class Cvs(FetchMethod):
         # tar them up to a defined filename
         workdir = None
         if 'fullpath' in ud.parm:
-            workdir = pkgdir
+            workdir = ud.pkgdir
             cmd = "tar %s -czf %s %s" % (tar_flags, ud.localpath, localdir)
         else:
             workdir = os.path.dirname(os.path.realpath(moddir))
@@ -151,9 +152,6 @@ class Cvs(FetchMethod):
     def clean(self, ud, d):
         """ Clean CVS Files and tarballs """
 
-        pkg = d.getVar('PN')
-        pkgdir = os.path.join(d.getVar("CVSDIR"), pkg)
-
-        bb.utils.remove(pkgdir, True)
+        bb.utils.remove(ud.pkgdir, True)
         bb.utils.remove(ud.localpath)
 
diff --git a/bitbake/lib/bb/fetch2/git.py b/bitbake/lib/bb/fetch2/git.py
index 2ce9395f..d17e2f07 100644
--- a/bitbake/lib/bb/fetch2/git.py
+++ b/bitbake/lib/bb/fetch2/git.py
@@ -63,10 +63,12 @@ import errno
 import fnmatch
 import os
 import re
+import shlex
 import subprocess
 import tempfile
 import bb
 import bb.progress
+from contextlib import contextmanager
 from   bb.fetch2 import FetchMethod
 from   bb.fetch2 import runfetchcmd
 from   bb.fetch2 import logger
@@ -140,6 +142,10 @@ class Git(FetchMethod):
             ud.proto = 'file'
         else:
             ud.proto = "git"
+        if ud.host == "github.com" and ud.proto == "git":
+            # github stopped supporting git protocol
+            # https://github.blog/2021-09-01-improving-git-protocol-security-github/#no-more-unauthenticated-git
+            ud.proto = "https"
 
         if not ud.proto in ('git', 'file', 'ssh', 'http', 'https', 'rsync'):
             raise bb.fetch2.ParameterError("Invalid protocol type", ud.url)
@@ -219,7 +225,12 @@ class Git(FetchMethod):
             ud.shallow = False
 
         if ud.usehead:
-            ud.unresolvedrev['default'] = 'HEAD'
+            # When usehead is set let's associate 'HEAD' with the unresolved
+            # rev of this repository. This will get resolved into a revision
+            # later. If an actual revision happens to have also been provided
+            # then this setting will be overridden.
+            for name in ud.names:
+                ud.unresolvedrev[name] = 'HEAD'
 
         ud.basecmd = d.getVar("FETCHCMD_git") or "git -c core.fsyncobjectfiles=0"
 
@@ -236,7 +247,7 @@ class Git(FetchMethod):
                     ud.unresolvedrev[name] = ud.revisions[name]
                 ud.revisions[name] = self.latest_revision(ud, d, name)
 
-        gitsrcname = '%s%s' % (ud.host.replace(':', '.'), ud.path.replace('/', '.').replace('*', '.'))
+        gitsrcname = '%s%s' % (ud.host.replace(':', '.'), ud.path.replace('/', '.').replace('*', '.').replace(' ','_'))
         if gitsrcname.startswith('.'):
             gitsrcname = gitsrcname[1:]
 
@@ -342,7 +353,7 @@ class Git(FetchMethod):
             # We do this since git will use a "-l" option automatically for local urls where possible
             if repourl.startswith("file://"):
                 repourl = repourl[7:]
-            clone_cmd = "LANG=C %s clone --bare --mirror %s %s --progress" % (ud.basecmd, repourl, ud.clonedir)
+            clone_cmd = "LANG=C %s clone --bare --mirror %s %s --progress" % (ud.basecmd, shlex.quote(repourl), ud.clonedir)
             if ud.proto.lower() != 'file':
                 bb.fetch2.check_network_access(d, clone_cmd, ud.url)
             progresshandler = GitProgressHandler(d)
@@ -354,8 +365,8 @@ class Git(FetchMethod):
             if "origin" in output:
               runfetchcmd("%s remote rm origin" % ud.basecmd, d, workdir=ud.clonedir)
 
-            runfetchcmd("%s remote add --mirror=fetch origin %s" % (ud.basecmd, repourl), d, workdir=ud.clonedir)
-            fetch_cmd = "LANG=C %s fetch -f --progress %s refs/*:refs/*" % (ud.basecmd, repourl)
+            runfetchcmd("%s remote add --mirror=fetch origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=ud.clonedir)
+            fetch_cmd = "LANG=C %s fetch -f --progress %s refs/*:refs/*" % (ud.basecmd, shlex.quote(repourl))
             if ud.proto.lower() != 'file':
                 bb.fetch2.check_network_access(d, fetch_cmd, ud.url)
             progresshandler = GitProgressHandler(d)
@@ -378,7 +389,50 @@ class Git(FetchMethod):
             if missing_rev:
                 raise bb.fetch2.FetchError("Unable to find revision %s even from upstream" % missing_rev)
 
+        if self._contains_lfs(ud, d, ud.clonedir) and self._need_lfs(ud):
+            # Unpack temporary working copy, use it to run 'git checkout' to force pre-fetching
+            # of all LFS blobs needed at the the srcrev.
+            #
+            # It would be nice to just do this inline here by running 'git-lfs fetch'
+            # on the bare clonedir, but that operation requires a working copy on some
+            # releases of Git LFS.
+            tmpdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
+            try:
+                # Do the checkout. This implicitly involves a Git LFS fetch.
+                Git.unpack(self, ud, tmpdir, d)
+
+                # Scoop up a copy of any stuff that Git LFS downloaded. Merge them into
+                # the bare clonedir.
+                #
+                # As this procedure is invoked repeatedly on incremental fetches as
+                # a recipe's SRCREV is bumped throughout its lifetime, this will
+                # result in a gradual accumulation of LFS blobs in <ud.clonedir>/lfs
+                # corresponding to all the blobs reachable from the different revs
+                # fetched across time.
+                #
+                # Only do this if the unpack resulted in a .git/lfs directory being
+                # created; this only happens if at least one blob needed to be
+                # downloaded.
+                if os.path.exists(os.path.join(tmpdir, "git", ".git", "lfs")):
+                    runfetchcmd("tar -cf - lfs | tar -xf - -C %s" % ud.clonedir, d, workdir="%s/git/.git" % tmpdir)
+            finally:
+                bb.utils.remove(tmpdir, recurse=True)
+
     def build_mirror_data(self, ud, d):
+
+        # Create as a temp file and move atomically into position to avoid races
+        @contextmanager
+        def create_atomic(filename):
+            fd, tfile = tempfile.mkstemp(dir=os.path.dirname(filename))
+            try:
+                yield tfile
+                umask = os.umask(0o666)
+                os.umask(umask)
+                os.chmod(tfile, (0o666 & ~umask))
+                os.rename(tfile, filename)
+            finally:
+                os.close(fd)
+
         if ud.shallow and ud.write_shallow_tarballs:
             if not os.path.exists(ud.fullshallow):
                 if os.path.islink(ud.fullshallow):
@@ -389,7 +443,8 @@ class Git(FetchMethod):
                     self.clone_shallow_local(ud, shallowclone, d)
 
                     logger.info("Creating tarball of git repository")
-                    runfetchcmd("tar -czf %s ." % ud.fullshallow, d, workdir=shallowclone)
+                    with create_atomic(ud.fullshallow) as tfile:
+                        runfetchcmd("tar -czf %s ." % tfile, d, workdir=shallowclone)
                     runfetchcmd("touch %s.done" % ud.fullshallow, d)
                 finally:
                     bb.utils.remove(tempdir, recurse=True)
@@ -398,7 +453,8 @@ class Git(FetchMethod):
                 os.unlink(ud.fullmirror)
 
             logger.info("Creating tarball of git repository")
-            runfetchcmd("tar -czf %s ." % ud.fullmirror, d, workdir=ud.clonedir)
+            with create_atomic(ud.fullmirror) as tfile:
+                runfetchcmd("tar -czf %s ." % tfile, d, workdir=ud.clonedir)
             runfetchcmd("touch %s.done" % ud.fullmirror, d)
 
     def clone_shallow_local(self, ud, dest, d):
@@ -473,7 +529,10 @@ class Git(FetchMethod):
         if os.path.exists(destdir):
             bb.utils.prunedir(destdir)
 
-        need_lfs = ud.parm.get("lfs", "1") == "1"
+        need_lfs = self._need_lfs(ud)
+
+        if not need_lfs:
+            ud.basecmd = "GIT_LFS_SKIP_SMUDGE=1 " + ud.basecmd
 
         source_found = False
         source_error = []
@@ -501,12 +560,12 @@ class Git(FetchMethod):
             raise bb.fetch2.UnpackError("No up to date source found: " + "; ".join(source_error), ud.url)
 
         repourl = self._get_repo_url(ud)
-        runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, repourl), d, workdir=destdir)
+        runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, shlex.quote(repourl)), d, workdir=destdir)
 
         if self._contains_lfs(ud, d, destdir):
             if need_lfs and not self._find_git_lfs(d):
                 raise bb.fetch2.FetchError("Repository %s has LFS content, install git-lfs on host to download (or set lfs=0 to ignore it)" % (repourl))
-            else:
+            elif not need_lfs:
                 bb.note("Repository %s has LFS content but it is not being fetched" % (repourl))
 
         if not ud.nocheckout:
@@ -559,12 +618,28 @@ class Git(FetchMethod):
             raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output))
         return output.split()[0] != "0"
 
+    def _need_lfs(self, ud):
+        return ud.parm.get("lfs", "1") == "1"
+
     def _contains_lfs(self, ud, d, wd):
         """
         Check if the repository has 'lfs' (large file) content
         """
-        cmd = "%s grep lfs HEAD:.gitattributes | wc -l" % (
-                ud.basecmd)
+
+        if not ud.nobranch:
+            branchname = ud.branches[ud.names[0]]
+        else:
+            branchname = "master"
+
+        # The bare clonedir doesn't use the remote names; it has the branch immediately.
+        if wd == ud.clonedir:
+            refname = ud.branches[ud.names[0]]
+        else:
+            refname = "origin/%s" % ud.branches[ud.names[0]]
+
+        cmd = "%s grep lfs %s:.gitattributes | wc -l" % (
+            ud.basecmd, refname)
+
         try:
             output = runfetchcmd(cmd, d, quiet=True, workdir=wd)
             if int(output) > 0:
@@ -584,6 +659,11 @@ class Git(FetchMethod):
         """
         Return the repository URL
         """
+        # Note that we do not support passwords directly in the git urls. There are several
+        # reasons. SRC_URI can be written out to things like buildhistory and people don't
+        # want to leak passwords like that. Its also all too easy to share metadata without 
+        # removing the password. ssh keys, ~/.netrc and ~/.ssh/config files can be used as
+        # alternatives so we will not take patches adding password support here.
         if ud.user:
             username = ud.user + '@'
         else:
@@ -614,7 +694,7 @@ class Git(FetchMethod):
         try:
             repourl = self._get_repo_url(ud)
             cmd = "%s ls-remote %s %s" % \
-                (ud.basecmd, repourl, search)
+                (ud.basecmd, shlex.quote(repourl), search)
             if ud.proto.lower() != 'file':
                 bb.fetch2.check_network_access(d, cmd, repourl)
             output = runfetchcmd(cmd, d, True)
diff --git a/bitbake/lib/bb/fetch2/gitsm.py b/bitbake/lib/bb/fetch2/gitsm.py
index e7083001..a4527bf3 100644
--- a/bitbake/lib/bb/fetch2/gitsm.py
+++ b/bitbake/lib/bb/fetch2/gitsm.py
@@ -78,7 +78,7 @@ class GitSM(Git):
                     module_hash = ""
 
                 if not module_hash:
-                    logger.debug(1, "submodule %s is defined, but is not initialized in the repository. Skipping", m)
+                    logger.debug("submodule %s is defined, but is not initialized in the repository. Skipping", m)
                     continue
 
                 submodules.append(m)
@@ -143,12 +143,43 @@ class GitSM(Git):
         try:
             # Check for the nugget dropped by the download operation
             known_srcrevs = runfetchcmd("%s config --get-all bitbake.srcrev" % \
-                            (ud.basecmd), d, workdir=ud.clonedir)
+                                        (ud.basecmd), d, workdir=ud.clonedir)
 
-            if ud.revisions[ud.names[0]] not in known_srcrevs.split():
-                return True
+            if ud.revisions[ud.names[0]] in known_srcrevs.split():
+                return False
         except bb.fetch2.FetchError:
-            # No srcrev nuggets, so this is new and needs to be updated
+            pass
+
+        need_update_list = []
+        def need_update_submodule(ud, url, module, modpath, workdir, d):
+            url += ";bareclone=1;nobranch=1"
+
+            try:
+                newfetch = Fetch([url], d, cache=False)
+                new_ud = newfetch.ud[url]
+                if new_ud.method.need_update(new_ud, d):
+                    need_update_list.append(modpath)
+            except Exception as e:
+                logger.error('gitsm: submodule update check failed: %s %s' % (type(e).__name__, str(e)))
+                need_update_result = True
+
+        # If we're using a shallow mirror tarball it needs to be unpacked
+        # temporarily so that we can examine the .gitmodules file
+        if ud.shallow and os.path.exists(ud.fullshallow) and not os.path.exists(ud.clonedir):
+            tmpdir = tempfile.mkdtemp(dir=d.getVar("DL_DIR"))
+            runfetchcmd("tar -xzf %s" % ud.fullshallow, d, workdir=tmpdir)
+            self.process_submodules(ud, tmpdir, need_update_submodule, d)
+            shutil.rmtree(tmpdir)
+        else:
+            self.process_submodules(ud, ud.clonedir, need_update_submodule, d)
+            if len(need_update_list) == 0:
+                # We already have the required commits of all submodules. Drop
+                # a nugget so we don't need to check again.
+                runfetchcmd("%s config --add bitbake.srcrev %s" % \
+                            (ud.basecmd, ud.revisions[ud.names[0]]), d, workdir=ud.clonedir)
+
+        if len(need_update_list) > 0:
+            logger.debug('gitsm: Submodules requiring update: %s' % (' '.join(need_update_list)))
             return True
 
         return False
@@ -163,9 +194,6 @@ class GitSM(Git):
             try:
                 newfetch = Fetch([url], d, cache=False)
                 newfetch.download()
-                # Drop a nugget to add each of the srcrevs we've fetched (used by need_update)
-                runfetchcmd("%s config --add bitbake.srcrev %s" % \
-                            (ud.basecmd, ud.revisions[ud.names[0]]), d, workdir=workdir)
             except Exception as e:
                 logger.error('gitsm: submodule download failed: %s %s' % (type(e).__name__, str(e)))
                 raise
@@ -181,6 +209,9 @@ class GitSM(Git):
             shutil.rmtree(tmpdir)
         else:
             self.process_submodules(ud, ud.clonedir, download_submodule, d)
+            # Drop a nugget for the srcrev we've fetched (used by need_update)
+            runfetchcmd("%s config --add bitbake.srcrev %s" % \
+                        (ud.basecmd, ud.revisions[ud.names[0]]), d, workdir=ud.clonedir)
 
     def unpack(self, ud, destdir, d):
         def unpack_submodules(ud, url, module, modpath, workdir, d):
@@ -223,3 +254,24 @@ class GitSM(Git):
             # up the configuration and checks out the files.  The main project config should remain
             # unmodified, and no download from the internet should occur.
             runfetchcmd("%s submodule update --recursive --no-fetch" % (ud.basecmd), d, quiet=True, workdir=ud.destdir)
+
+    def implicit_urldata(self, ud, d):
+        import shutil, subprocess, tempfile
+
+        urldata = []
+        def add_submodule(ud, url, module, modpath, workdir, d):
+            url += ";bareclone=1;nobranch=1"
+            newfetch = Fetch([url], d, cache=False)
+            urldata.extend(newfetch.expanded_urldata())
+
+        # If we're using a shallow mirror tarball it needs to be unpacked
+        # temporarily so that we can examine the .gitmodules file
+        if ud.shallow and os.path.exists(ud.fullshallow) and ud.method.need_update(ud, d):
+            tmpdir = tempfile.mkdtemp(dir=d.getVar("DL_DIR"))
+            subprocess.check_call("tar -xzf %s" % ud.fullshallow, cwd=tmpdir, shell=True)
+            self.process_submodules(ud, tmpdir, add_submodule, d)
+            shutil.rmtree(tmpdir)
+        else:
+            self.process_submodules(ud, ud.clonedir, add_submodule, d)
+
+        return urldata
diff --git a/bitbake/lib/bb/fetch2/hg.py b/bitbake/lib/bb/fetch2/hg.py
index 8f503701..063e1300 100644
--- a/bitbake/lib/bb/fetch2/hg.py
+++ b/bitbake/lib/bb/fetch2/hg.py
@@ -150,7 +150,7 @@ class Hg(FetchMethod):
     def download(self, ud, d):
         """Fetch url"""
 
-        logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
+        logger.debug2("Fetch: checking for module directory '" + ud.moddir + "'")
 
         # If the checkout doesn't exist and the mirror tarball does, extract it
         if not os.path.exists(ud.pkgdir) and os.path.exists(ud.fullmirror):
@@ -160,7 +160,7 @@ class Hg(FetchMethod):
         if os.access(os.path.join(ud.moddir, '.hg'), os.R_OK):
             # Found the source, check whether need pull
             updatecmd = self._buildhgcommand(ud, d, "update")
-            logger.debug(1, "Running %s", updatecmd)
+            logger.debug("Running %s", updatecmd)
             try:
                 runfetchcmd(updatecmd, d, workdir=ud.moddir)
             except bb.fetch2.FetchError:
@@ -168,7 +168,7 @@ class Hg(FetchMethod):
                 pullcmd = self._buildhgcommand(ud, d, "pull")
                 logger.info("Pulling " + ud.url)
                 # update sources there
-                logger.debug(1, "Running %s", pullcmd)
+                logger.debug("Running %s", pullcmd)
                 bb.fetch2.check_network_access(d, pullcmd, ud.url)
                 runfetchcmd(pullcmd, d, workdir=ud.moddir)
                 try:
@@ -183,14 +183,14 @@ class Hg(FetchMethod):
             logger.info("Fetch " + ud.url)
             # check out sources there
             bb.utils.mkdirhier(ud.pkgdir)
-            logger.debug(1, "Running %s", fetchcmd)
+            logger.debug("Running %s", fetchcmd)
             bb.fetch2.check_network_access(d, fetchcmd, ud.url)
             runfetchcmd(fetchcmd, d, workdir=ud.pkgdir)
 
         # Even when we clone (fetch), we still need to update as hg's clone
         # won't checkout the specified revision if its on a branch
         updatecmd = self._buildhgcommand(ud, d, "update")
-        logger.debug(1, "Running %s", updatecmd)
+        logger.debug("Running %s", updatecmd)
         runfetchcmd(updatecmd, d, workdir=ud.moddir)
 
     def clean(self, ud, d):
@@ -247,9 +247,9 @@ class Hg(FetchMethod):
         if scmdata != "nokeep":
             proto = ud.parm.get('protocol', 'http')
             if not os.access(os.path.join(codir, '.hg'), os.R_OK):
-                logger.debug(2, "Unpack: creating new hg repository in '" + codir + "'")
+                logger.debug2("Unpack: creating new hg repository in '" + codir + "'")
                 runfetchcmd("%s init %s" % (ud.basecmd, codir), d)
-            logger.debug(2, "Unpack: updating source in '" + codir + "'")
+            logger.debug2("Unpack: updating source in '" + codir + "'")
             if ud.user and ud.pswd:
                 runfetchcmd("%s --config auth.default.prefix=* --config auth.default.username=%s --config auth.default.password=%s --config \"auth.default.schemes=%s\" pull %s" % (ud.basecmd, ud.user, ud.pswd, proto, ud.moddir), d, workdir=codir)
             else:
@@ -259,5 +259,5 @@ class Hg(FetchMethod):
             else:
                 runfetchcmd("%s up -C %s" % (ud.basecmd, revflag), d, workdir=codir)
         else:
-            logger.debug(2, "Unpack: extracting source to '" + codir + "'")
+            logger.debug2("Unpack: extracting source to '" + codir + "'")
             runfetchcmd("%s archive -t files %s %s" % (ud.basecmd, revflag, codir), d, workdir=ud.moddir)
diff --git a/bitbake/lib/bb/fetch2/local.py b/bitbake/lib/bb/fetch2/local.py
index 01d9ff9f..e7d1c8c5 100644
--- a/bitbake/lib/bb/fetch2/local.py
+++ b/bitbake/lib/bb/fetch2/local.py
@@ -17,7 +17,7 @@ import os
 import urllib.request, urllib.parse, urllib.error
 import bb
 import bb.utils
-from   bb.fetch2 import FetchMethod, FetchError
+from   bb.fetch2 import FetchMethod, FetchError, ParameterError
 from   bb.fetch2 import logger
 
 class Local(FetchMethod):
@@ -33,6 +33,8 @@ class Local(FetchMethod):
         ud.basename = os.path.basename(ud.decodedurl)
         ud.basepath = ud.decodedurl
         ud.needdonestamp = False
+        if "*" in ud.decodedurl:
+            raise bb.fetch2.ParameterError("file:// urls using globbing are no longer supported. Please place the files in a directory and reference that instead.", ud.url)
         return
 
     def localpath(self, urldata, d):
@@ -52,26 +54,18 @@ class Local(FetchMethod):
             return [path]
         filespath = d.getVar('FILESPATH')
         if filespath:
-            logger.debug(2, "Searching for %s in paths:\n    %s" % (path, "\n    ".join(filespath.split(":"))))
+            logger.debug2("Searching for %s in paths:\n    %s" % (path, "\n    ".join(filespath.split(":"))))
             newpath, hist = bb.utils.which(filespath, path, history=True)
             searched.extend(hist)
-        if (not newpath or not os.path.exists(newpath)) and path.find("*") != -1:
-            # For expressions using '*', best we can do is take the first directory in FILESPATH that exists
-            newpath, hist = bb.utils.which(filespath, ".", history=True)
-            searched.extend(hist)
-            logger.debug(2, "Searching for %s in path: %s" % (path, newpath))
-            return searched
         if not os.path.exists(newpath):
             dldirfile = os.path.join(d.getVar("DL_DIR"), path)
-            logger.debug(2, "Defaulting to %s for %s" % (dldirfile, path))
+            logger.debug2("Defaulting to %s for %s" % (dldirfile, path))
             bb.utils.mkdirhier(os.path.dirname(dldirfile))
             searched.append(dldirfile)
             return searched
         return searched
 
     def need_update(self, ud, d):
-        if ud.url.find("*") != -1:
-            return False
         if os.path.exists(ud.localpath):
             return False
         return True
@@ -95,9 +89,6 @@ class Local(FetchMethod):
         """
         Check the status of the url
         """
-        if urldata.localpath.find("*") != -1:
-            logger.info("URL %s looks like a glob and was therefore not checked.", urldata.url)
-            return True
         if os.path.exists(urldata.localpath):
             return True
         return False
diff --git a/bitbake/lib/bb/fetch2/npmsw.py b/bitbake/lib/bb/fetch2/npmsw.py
index 0c3511d8..fdecbc6d 100644
--- a/bitbake/lib/bb/fetch2/npmsw.py
+++ b/bitbake/lib/bb/fetch2/npmsw.py
@@ -29,6 +29,8 @@ from bb.fetch2.npm import npm_integrity
 from bb.fetch2.npm import npm_localfile
 from bb.fetch2.npm import npm_unpack
 from bb.utils import is_semver
+from bb.utils import lockfile
+from bb.utils import unlockfile
 
 def foreach_dependencies(shrinkwrap, callback=None, dev=False):
     """
@@ -187,7 +189,9 @@ class NpmShrinkWrap(FetchMethod):
             proxy_ud = ud.proxy.ud[proxy_url]
             proxy_d = ud.proxy.d
             proxy_ud.setup_localpath(proxy_d)
+            lf = lockfile(proxy_ud.lockfile)
             returns.append(handle(proxy_ud.method, proxy_ud, proxy_d))
+            unlockfile(lf)
         return returns
 
     def verify_donestamp(self, ud, d):
diff --git a/bitbake/lib/bb/fetch2/osc.py b/bitbake/lib/bb/fetch2/osc.py
index 8f091efd..d9ce4439 100644
--- a/bitbake/lib/bb/fetch2/osc.py
+++ b/bitbake/lib/bb/fetch2/osc.py
@@ -8,12 +8,15 @@ Based on the svn "Fetch" implementation.
 """
 
 import logging
+import os
 import  bb
 from    bb.fetch2 import FetchMethod
 from    bb.fetch2 import FetchError
 from    bb.fetch2 import MissingParameterError
 from    bb.fetch2 import runfetchcmd
 
+logger = logging.getLogger(__name__)
+
 class Osc(FetchMethod):
     """Class to fetch a module or modules from Opensuse build server
        repositories."""
@@ -81,13 +84,13 @@ class Osc(FetchMethod):
         Fetch url
         """
 
-        logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
+        logger.debug2("Fetch: checking for module directory '" + ud.moddir + "'")
 
         if os.access(os.path.join(d.getVar('OSCDIR'), ud.path, ud.module), os.R_OK):
             oscupdatecmd = self._buildosccommand(ud, d, "update")
             logger.info("Update "+ ud.url)
             # update sources there
-            logger.debug(1, "Running %s", oscupdatecmd)
+            logger.debug("Running %s", oscupdatecmd)
             bb.fetch2.check_network_access(d, oscupdatecmd, ud.url)
             runfetchcmd(oscupdatecmd, d, workdir=ud.moddir)
         else:
@@ -95,7 +98,7 @@ class Osc(FetchMethod):
             logger.info("Fetch " + ud.url)
             # check out sources there
             bb.utils.mkdirhier(ud.pkgdir)
-            logger.debug(1, "Running %s", oscfetchcmd)
+            logger.debug("Running %s", oscfetchcmd)
             bb.fetch2.check_network_access(d, oscfetchcmd, ud.url)
             runfetchcmd(oscfetchcmd, d, workdir=ud.pkgdir)
 
diff --git a/bitbake/lib/bb/fetch2/perforce.py b/bitbake/lib/bb/fetch2/perforce.py
index f57c2a4f..e2a41a4a 100644
--- a/bitbake/lib/bb/fetch2/perforce.py
+++ b/bitbake/lib/bb/fetch2/perforce.py
@@ -1,6 +1,20 @@
 """
 BitBake 'Fetch' implementation for perforce
 
+Supported SRC_URI options are:
+
+- module
+   The top-level location to fetch while preserving the remote paths
+
+   The value of module can point to either a directory or a file. The result,
+   in both cases, is that the fetcher will preserve all file paths starting
+   from the module path. That is, the top-level directory in the module value
+   will also be the top-level directory in P4DIR.
+
+- remotepath
+   If the value "keep" is given, the full depot location of each file is
+   preserved in P4DIR. This option overrides the effect of the module option.
+
 """
 
 # Copyright (C) 2003, 2004  Chris Larson
@@ -17,6 +31,36 @@ from   bb.fetch2 import FetchError
 from   bb.fetch2 import logger
 from   bb.fetch2 import runfetchcmd
 
+class PerforceProgressHandler (bb.progress.BasicProgressHandler):
+    """
+    Implements basic progress information for perforce, based on the number of
+    files to be downloaded.
+
+    The p4 print command will print one line per file, therefore it can be used
+    to "count" the number of files already completed and give an indication of
+    the progress.
+    """
+    def __init__(self, d, num_files):
+        self._num_files = num_files
+        self._count = 0
+        super(PerforceProgressHandler, self).__init__(d)
+
+        # Send an initial progress event so the bar gets shown
+        self._fire_progress(-1)
+
+    def write(self, string):
+        self._count = self._count + 1
+
+        percent = int(100.0 * float(self._count) / float(self._num_files))
+
+        # In case something goes wrong, we try to preserve our sanity
+        if percent > 100:
+            percent = 100
+
+        self.update(percent)
+
+        super(PerforceProgressHandler, self).write(string)
+
 class Perforce(FetchMethod):
     """ Class to fetch from perforce repositories """
     def supports(self, ud, d):
@@ -46,31 +90,51 @@ class Perforce(FetchMethod):
         p4port = d.getVar('P4PORT')
 
         if p4port:
-            logger.debug(1, 'Using recipe provided P4PORT: %s' % p4port)
+            logger.debug('Using recipe provided P4PORT: %s' % p4port)
             ud.host = p4port
         else:
-            logger.debug(1, 'Trying to use P4CONFIG to automatically set P4PORT...')
+            logger.debug('Trying to use P4CONFIG to automatically set P4PORT...')
             ud.usingp4config = True
             p4cmd = '%s info | grep "Server address"' % ud.basecmd
             bb.fetch2.check_network_access(d, p4cmd, ud.url)
             ud.host = runfetchcmd(p4cmd, d, True)
             ud.host = ud.host.split(': ')[1].strip()
-            logger.debug(1, 'Determined P4PORT to be: %s' % ud.host)
+            logger.debug('Determined P4PORT to be: %s' % ud.host)
             if not ud.host:
                 raise FetchError('Could not determine P4PORT from P4CONFIG')
-	
+
+        # Fetcher options
+        ud.module = ud.parm.get('module')
+        ud.keepremotepath = (ud.parm.get('remotepath', '') == 'keep')
+
         if ud.path.find('/...') >= 0:
             ud.pathisdir = True
         else:
             ud.pathisdir = False
 
+        # Avoid using the "/..." syntax in SRC_URI when a module value is given
+        if ud.pathisdir and ud.module:
+            raise FetchError('SRC_URI depot path cannot not end in /... when a module value is given')
+
         cleanedpath = ud.path.replace('/...', '').replace('/', '.')
         cleanedhost = ud.host.replace(':', '.')
+
+        cleanedmodule = ""
+        # Merge the path and module into the final depot location
+        if ud.module:
+            if ud.module.find('/') == 0:
+                raise FetchError('module cannot begin with /')
+            ud.path = os.path.join(ud.path, ud.module)
+
+            # Append the module path to the local pkg name
+            cleanedmodule = ud.module.replace('/...', '').replace('/', '.')
+            cleanedpath += '--%s' % cleanedmodule
+
         ud.pkgdir = os.path.join(ud.dldir, cleanedhost, cleanedpath)
 
         ud.setup_revisions(d)
 
-        ud.localfile = d.expand('%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, ud.revision))
+        ud.localfile = d.expand('%s_%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, cleandedmodule, ud.revision))
 
     def _buildp4command(self, ud, d, command, depot_filename=None):
         """
@@ -95,10 +159,20 @@ class Perforce(FetchMethod):
             pathnrev = '%s' % (ud.path)
 
         if depot_filename:
-            if ud.pathisdir: # Remove leading path to obtain filename
+            if ud.keepremotepath:
+                # preserve everything, remove the leading //
+                filename = depot_filename.lstrip('/')
+            elif ud.module:
+                # remove everything up to the module path
+                modulepath = ud.module.rstrip('/...')
+                filename = depot_filename[depot_filename.rfind(modulepath):]
+            elif ud.pathisdir:
+                # Remove leading (visible) path to obtain the filepath
                 filename = depot_filename[len(ud.path)-1:]
             else:
+                # Remove everything, except the filename
                 filename = depot_filename[depot_filename.rfind('/'):]
+
             filename = filename[:filename.find('#')] # Remove trailing '#rev'
 
         if command == 'changes':
@@ -134,7 +208,7 @@ class Perforce(FetchMethod):
         for filename in p4fileslist:
             item = filename.split(' - ')
             lastaction = item[1].split()
-            logger.debug(1, 'File: %s Last Action: %s' % (item[0], lastaction[0]))
+            logger.debug('File: %s Last Action: %s' % (item[0], lastaction[0]))
             if lastaction[0] == 'delete':
                 continue
             filelist.append(item[0])
@@ -150,10 +224,12 @@ class Perforce(FetchMethod):
         bb.utils.remove(ud.pkgdir, True)
         bb.utils.mkdirhier(ud.pkgdir)
 
+        progresshandler = PerforceProgressHandler(d, len(filelist))
+
         for afile in filelist:
             p4fetchcmd = self._buildp4command(ud, d, 'print', afile)
             bb.fetch2.check_network_access(d, p4fetchcmd, ud.url)
-            runfetchcmd(p4fetchcmd, d, workdir=ud.pkgdir)
+            runfetchcmd(p4fetchcmd, d, workdir=ud.pkgdir, log=progresshandler)
 
         runfetchcmd('tar -czf %s p4' % (ud.localpath), d, cleanup=[ud.localpath], workdir=ud.pkgdir)
 
@@ -179,7 +255,7 @@ class Perforce(FetchMethod):
             raise FetchError('Could not determine the latest perforce changelist')
 
         tipcset = tip.split(' ')[1]
-        logger.debug(1, 'p4 tip found to be changelist %s' % tipcset)
+        logger.debug('p4 tip found to be changelist %s' % tipcset)
         return tipcset
 
     def sortable_revision(self, ud, d, name):
diff --git a/bitbake/lib/bb/fetch2/repo.py b/bitbake/lib/bb/fetch2/repo.py
index 2bdbbd40..fa4cb814 100644
--- a/bitbake/lib/bb/fetch2/repo.py
+++ b/bitbake/lib/bb/fetch2/repo.py
@@ -47,7 +47,7 @@ class Repo(FetchMethod):
         """Fetch url"""
 
         if os.access(os.path.join(d.getVar("DL_DIR"), ud.localfile), os.R_OK):
-            logger.debug(1, "%s already exists (or was stashed). Skipping repo init / sync.", ud.localpath)
+            logger.debug("%s already exists (or was stashed). Skipping repo init / sync.", ud.localpath)
             return
 
         repodir = d.getVar("REPODIR") or (d.getVar("DL_DIR") + "/repo")
diff --git a/bitbake/lib/bb/fetch2/ssh.py b/bitbake/lib/bb/fetch2/ssh.py
index 5e982ecf..2c8557e1 100644
--- a/bitbake/lib/bb/fetch2/ssh.py
+++ b/bitbake/lib/bb/fetch2/ssh.py
@@ -31,8 +31,7 @@ IETF secsh internet draft:
 #
 
 import re, os
-from   bb.fetch2 import FetchMethod
-from   bb.fetch2 import runfetchcmd
+from bb.fetch2 import check_network_access, FetchMethod, ParameterError, runfetchcmd
 
 
 __pattern__ = re.compile(r'''
@@ -65,7 +64,7 @@ class SSH(FetchMethod):
 
     def urldata_init(self, urldata, d):
         if 'protocol' in urldata.parm and urldata.parm['protocol'] == 'git':
-            raise bb.fetch2.ParameterError(
+            raise ParameterError(
                 "Invalid protocol - if you wish to fetch from a git " +
                 "repository using ssh, you need to use " +
                 "git:// prefix with protocol=ssh", urldata.url)
@@ -105,7 +104,7 @@ class SSH(FetchMethod):
             dldir
         )
 
-        bb.fetch2.check_network_access(d, cmd, urldata.url)
+        check_network_access(d, cmd, urldata.url)
 
         runfetchcmd(cmd, d)
 
diff --git a/bitbake/lib/bb/fetch2/svn.py b/bitbake/lib/bb/fetch2/svn.py
index 971a5add..80102b44 100644
--- a/bitbake/lib/bb/fetch2/svn.py
+++ b/bitbake/lib/bb/fetch2/svn.py
@@ -86,7 +86,7 @@ class Svn(FetchMethod):
         if command == "info":
             svncmd = "%s info %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
         elif command == "log1":
-            svncmd = "%s log --limit 1 %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
+            svncmd = "%s log --limit 1 --quiet %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
         else:
             suffix = ""
 
@@ -116,7 +116,7 @@ class Svn(FetchMethod):
     def download(self, ud, d):
         """Fetch url"""
 
-        logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
+        logger.debug2("Fetch: checking for module directory '" + ud.moddir + "'")
 
         lf = bb.utils.lockfile(ud.svnlock)
 
@@ -129,7 +129,7 @@ class Svn(FetchMethod):
                     runfetchcmd(ud.basecmd + " upgrade", d, workdir=ud.moddir)
                 except FetchError:
                     pass
-                logger.debug(1, "Running %s", svncmd)
+                logger.debug("Running %s", svncmd)
                 bb.fetch2.check_network_access(d, svncmd, ud.url)
                 runfetchcmd(svncmd, d, workdir=ud.moddir)
             else:
@@ -137,7 +137,7 @@ class Svn(FetchMethod):
                 logger.info("Fetch " + ud.url)
                 # check out sources there
                 bb.utils.mkdirhier(ud.pkgdir)
-                logger.debug(1, "Running %s", svncmd)
+                logger.debug("Running %s", svncmd)
                 bb.fetch2.check_network_access(d, svncmd, ud.url)
                 runfetchcmd(svncmd, d, workdir=ud.pkgdir)
 
diff --git a/bitbake/lib/bb/fetch2/wget.py b/bitbake/lib/bb/fetch2/wget.py
index f7d1de26..784df70c 100644
--- a/bitbake/lib/bb/fetch2/wget.py
+++ b/bitbake/lib/bb/fetch2/wget.py
@@ -52,6 +52,12 @@ class WgetProgressHandler(bb.progress.LineFilterProgressHandler):
 
 
 class Wget(FetchMethod):
+
+    # CDNs like CloudFlare may do a 'browser integrity test' which can fail
+    # with the standard wget/urllib User-Agent, so pretend to be a modern
+    # browser.
+    user_agent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0"
+
     """Class to fetch urls via 'wget'"""
     def supports(self, ud, d):
         """
@@ -82,7 +88,7 @@ class Wget(FetchMethod):
 
         progresshandler = WgetProgressHandler(d)
 
-        logger.debug(2, "Fetching %s using command '%s'" % (ud.url, command))
+        logger.debug2("Fetching %s using command '%s'" % (ud.url, command))
         bb.fetch2.check_network_access(d, command, ud.url)
         runfetchcmd(command + ' --progress=dot -v', d, quiet, log=progresshandler, workdir=workdir)
 
@@ -208,10 +214,7 @@ class Wget(FetchMethod):
                         fetch.connection_cache.remove_connection(h.host, h.port)
                     raise urllib.error.URLError(err)
                 else:
-                    try:
-                        r = h.getresponse(buffering=True)
-                    except TypeError: # buffering kw not supported
-                        r = h.getresponse()
+                    r = h.getresponse()
 
                 # Pick apart the HTTPResponse object to get the addinfourl
                 # object initialized properly.
@@ -300,7 +303,7 @@ class Wget(FetchMethod):
             # Some servers (FusionForge, as used on Alioth) require that the
             # optional Accept header is set.
             r.add_header("Accept", "*/*")
-            r.add_header("User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/9.10 (karmic) Firefox/3.6.12")
+            r.add_header("User-Agent", self.user_agent)
             def add_basic_auth(login_str, request):
                 '''Adds Basic auth to http request, pass in login:password as string'''
                 import base64
@@ -323,11 +326,19 @@ class Wget(FetchMethod):
                 pass
         except urllib.error.URLError as e:
             if try_again:
-                logger.debug(2, "checkstatus: trying again")
+                logger.debug2("checkstatus: trying again")
+                return self.checkstatus(fetch, ud, d, False)
+            else:
+                # debug for now to avoid spamming the logs in e.g. remote sstate searches
+                logger.debug2("checkstatus() urlopen failed: %s" % e)
+                return False
+        except ConnectionResetError as e:
+            if try_again:
+                logger.debug2("checkstatus: trying again")
                 return self.checkstatus(fetch, ud, d, False)
             else:
                 # debug for now to avoid spamming the logs in e.g. remote sstate searches
-                logger.debug(2, "checkstatus() urlopen failed: %s" % e)
+                logger.debug2("checkstatus() urlopen failed: %s" % e)
                 return False
         return True
 
@@ -404,9 +415,8 @@ class Wget(FetchMethod):
         """
         f = tempfile.NamedTemporaryFile()
         with tempfile.TemporaryDirectory(prefix="wget-index-") as workdir, tempfile.NamedTemporaryFile(dir=workdir, prefix="wget-listing-") as f:
-            agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.12) Gecko/20101027 Ubuntu/9.10 (karmic) Firefox/3.6.12"
             fetchcmd = self.basecmd
-            fetchcmd += " -O " + f.name + " --user-agent='" + agent + "' '" + uri + "'"
+            fetchcmd += " -O " + f.name + " --user-agent='" + self.user_agent + "' '" + uri + "'"
             try:
                 self._runwget(ud, d, fetchcmd, True, workdir=workdir)
                 fetchresult = f.read()
@@ -462,7 +472,7 @@ class Wget(FetchMethod):
         version_dir = ['', '', '']
         version = ['', '', '']
 
-        dirver_regex = re.compile(r"(?P<pfx>\D*)(?P<ver>(\d+[\.\-_])+(\d+))")
+        dirver_regex = re.compile(r"(?P<pfx>\D*)(?P<ver>(\d+[\.\-_])*(\d+))")
         s = dirver_regex.search(dirver)
         if s:
             version_dir[1] = s.group('ver')
diff --git a/bitbake/lib/bb/main.py b/bitbake/lib/bb/main.py
index af2880f8..06bad495 100755
--- a/bitbake/lib/bb/main.py
+++ b/bitbake/lib/bb/main.py
@@ -119,178 +119,181 @@ warnings.filterwarnings("ignore", category=ImportWarning)
 warnings.filterwarnings("ignore", category=DeprecationWarning, module="<string>$")
 warnings.filterwarnings("ignore", message="With-statements now directly support multiple context managers")
 
-class BitBakeConfigParameters(cookerdata.ConfigParameters):
 
-    def parseCommandLine(self, argv=sys.argv):
-        parser = optparse.OptionParser(
-            formatter=BitbakeHelpFormatter(),
-            version="BitBake Build Tool Core version %s" % bb.__version__,
-            usage="""%prog [options] [recipename/target recipe:do_task ...]
+def create_bitbake_parser():
+    parser = optparse.OptionParser(
+        formatter=BitbakeHelpFormatter(),
+        version="BitBake Build Tool Core version %s" % bb.__version__,
+        usage="""%prog [options] [recipename/target recipe:do_task ...]
 
     Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
     It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
     will provide the layer, BBFILES and other configuration information.""")
 
-        parser.add_option("-b", "--buildfile", action="store", dest="buildfile", default=None,
-                          help="Execute tasks from a specific .bb recipe directly. WARNING: Does "
-                               "not handle any dependencies from other recipes.")
-
-        parser.add_option("-k", "--continue", action="store_false", dest="abort", default=True,
-                          help="Continue as much as possible after an error. While the target that "
-                               "failed and anything depending on it cannot be built, as much as "
-                               "possible will be built before stopping.")
-
-        parser.add_option("-f", "--force", action="store_true", dest="force", default=False,
-                          help="Force the specified targets/task to run (invalidating any "
-                               "existing stamp file).")
-
-        parser.add_option("-c", "--cmd", action="store", dest="cmd",
-                          help="Specify the task to execute. The exact options available "
-                               "depend on the metadata. Some examples might be 'compile'"
-                               " or 'populate_sysroot' or 'listtasks' may give a list of "
-                               "the tasks available.")
-
-        parser.add_option("-C", "--clear-stamp", action="store", dest="invalidate_stamp",
-                          help="Invalidate the stamp for the specified task such as 'compile' "
-                               "and then run the default task for the specified target(s).")
-
-        parser.add_option("-r", "--read", action="append", dest="prefile", default=[],
-                          help="Read the specified file before bitbake.conf.")
-
-        parser.add_option("-R", "--postread", action="append", dest="postfile", default=[],
-                          help="Read the specified file after bitbake.conf.")
-
-        parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
-                          help="Enable tracing of shell tasks (with 'set -x'). "
-                               "Also print bb.note(...) messages to stdout (in "
-                               "addition to writing them to ${T}/log.do_<task>).")
-
-        parser.add_option("-D", "--debug", action="count", dest="debug", default=0,
-                          help="Increase the debug level. You can specify this "
-                               "more than once. -D sets the debug level to 1, "
-                               "where only bb.debug(1, ...) messages are printed "
-                               "to stdout; -DD sets the debug level to 2, where "
-                               "both bb.debug(1, ...) and bb.debug(2, ...) "
-                               "messages are printed; etc. Without -D, no debug "
-                               "messages are printed. Note that -D only affects "
-                               "output to stdout. All debug messages are written "
-                               "to ${T}/log.do_taskname, regardless of the debug "
-                               "level.")
-
-        parser.add_option("-q", "--quiet", action="count", dest="quiet", default=0,
-                          help="Output less log message data to the terminal. You can specify this more than once.")
-
-        parser.add_option("-n", "--dry-run", action="store_true", dest="dry_run", default=False,
-                          help="Don't execute, just go through the motions.")
-
-        parser.add_option("-S", "--dump-signatures", action="append", dest="dump_signatures",
-                          default=[], metavar="SIGNATURE_HANDLER",
-                          help="Dump out the signature construction information, with no task "
-                               "execution. The SIGNATURE_HANDLER parameter is passed to the "
-                               "handler. Two common values are none and printdiff but the handler "
-                               "may define more/less. none means only dump the signature, printdiff"
-                               " means compare the dumped signature with the cached one.")
-
-        parser.add_option("-p", "--parse-only", action="store_true",
-                          dest="parse_only", default=False,
-                          help="Quit after parsing the BB recipes.")
-
-        parser.add_option("-s", "--show-versions", action="store_true",
-                          dest="show_versions", default=False,
-                          help="Show current and preferred versions of all recipes.")
-
-        parser.add_option("-e", "--environment", action="store_true",
-                          dest="show_environment", default=False,
-                          help="Show the global or per-recipe environment complete with information"
-                               " about where variables were set/changed.")
-
-        parser.add_option("-g", "--graphviz", action="store_true", dest="dot_graph", default=False,
-                          help="Save dependency tree information for the specified "
-                               "targets in the dot syntax.")
-
-        parser.add_option("-I", "--ignore-deps", action="append",
-                          dest="extra_assume_provided", default=[],
-                          help="Assume these dependencies don't exist and are already provided "
-                               "(equivalent to ASSUME_PROVIDED). Useful to make dependency "
-                               "graphs more appealing")
-
-        parser.add_option("-l", "--log-domains", action="append", dest="debug_domains", default=[],
-                          help="Show debug logging for the specified logging domains")
-
-        parser.add_option("-P", "--profile", action="store_true", dest="profile", default=False,
-                          help="Profile the command and save reports.")
-
-        # @CHOICES@ is substituted out by BitbakeHelpFormatter above
-        parser.add_option("-u", "--ui", action="store", dest="ui",
-                          default=os.environ.get('BITBAKE_UI', 'knotty'),
-                          help="The user interface to use (@CHOICES@ - default %default).")
-
-        parser.add_option("", "--token", action="store", dest="xmlrpctoken",
-                          default=os.environ.get("BBTOKEN"),
-                          help="Specify the connection token to be used when connecting "
-                               "to a remote server.")
-
-        parser.add_option("", "--revisions-changed", action="store_true",
-                          dest="revisions_changed", default=False,
-                          help="Set the exit code depending on whether upstream floating "
-                               "revisions have changed or not.")
-
-        parser.add_option("", "--server-only", action="store_true",
-                          dest="server_only", default=False,
-                          help="Run bitbake without a UI, only starting a server "
-                               "(cooker) process.")
-
-        parser.add_option("-B", "--bind", action="store", dest="bind", default=False,
-                          help="The name/address for the bitbake xmlrpc server to bind to.")
-
-        parser.add_option("-T", "--idle-timeout", type=float, dest="server_timeout",
-                          default=os.getenv("BB_SERVER_TIMEOUT"),
-                          help="Set timeout to unload bitbake server due to inactivity, "
-                                "set to -1 means no unload, "
-                                "default: Environment variable BB_SERVER_TIMEOUT.")
-
-        parser.add_option("", "--no-setscene", action="store_true",
-                          dest="nosetscene", default=False,
-                          help="Do not run any setscene tasks. sstate will be ignored and "
-                               "everything needed, built.")
-
-        parser.add_option("", "--skip-setscene", action="store_true",
-                          dest="skipsetscene", default=False,
-                          help="Skip setscene tasks if they would be executed. Tasks previously "
-                               "restored from sstate will be kept, unlike --no-setscene")
-
-        parser.add_option("", "--setscene-only", action="store_true",
-                          dest="setsceneonly", default=False,
-                          help="Only run setscene tasks, don't run any real tasks.")
-
-        parser.add_option("", "--remote-server", action="store", dest="remote_server",
-                          default=os.environ.get("BBSERVER"),
-                          help="Connect to the specified server.")
-
-        parser.add_option("-m", "--kill-server", action="store_true",
-                          dest="kill_server", default=False,
-                          help="Terminate any running bitbake server.")
-
-        parser.add_option("", "--observe-only", action="store_true",
-                          dest="observe_only", default=False,
-                          help="Connect to a server as an observing-only client.")
-
-        parser.add_option("", "--status-only", action="store_true",
-                          dest="status_only", default=False,
-                          help="Check the status of the remote bitbake server.")
-
-        parser.add_option("-w", "--write-log", action="store", dest="writeeventlog",
-                          default=os.environ.get("BBEVENTLOG"),
-                          help="Writes the event log of the build to a bitbake event json file. "
-                               "Use '' (empty string) to assign the name automatically.")
-
-        parser.add_option("", "--runall", action="append", dest="runall",
-                          help="Run the specified task for any recipe in the taskgraph of the specified target (even if it wouldn't otherwise have run).")
-
-        parser.add_option("", "--runonly", action="append", dest="runonly",
-                          help="Run only the specified task within the taskgraph of the specified targets (and any task dependencies those tasks may have).")
+    parser.add_option("-b", "--buildfile", action="store", dest="buildfile", default=None,
+                      help="Execute tasks from a specific .bb recipe directly. WARNING: Does "
+                           "not handle any dependencies from other recipes.")
+
+    parser.add_option("-k", "--continue", action="store_false", dest="abort", default=True,
+                      help="Continue as much as possible after an error. While the target that "
+                           "failed and anything depending on it cannot be built, as much as "
+                           "possible will be built before stopping.")
+
+    parser.add_option("-f", "--force", action="store_true", dest="force", default=False,
+                      help="Force the specified targets/task to run (invalidating any "
+                           "existing stamp file).")
+
+    parser.add_option("-c", "--cmd", action="store", dest="cmd",
+                      help="Specify the task to execute. The exact options available "
+                           "depend on the metadata. Some examples might be 'compile'"
+                           " or 'populate_sysroot' or 'listtasks' may give a list of "
+                           "the tasks available.")
+
+    parser.add_option("-C", "--clear-stamp", action="store", dest="invalidate_stamp",
+                      help="Invalidate the stamp for the specified task such as 'compile' "
+                           "and then run the default task for the specified target(s).")
+
+    parser.add_option("-r", "--read", action="append", dest="prefile", default=[],
+                      help="Read the specified file before bitbake.conf.")
+
+    parser.add_option("-R", "--postread", action="append", dest="postfile", default=[],
+                      help="Read the specified file after bitbake.conf.")
+
+    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
+                      help="Enable tracing of shell tasks (with 'set -x'). "
+                           "Also print bb.note(...) messages to stdout (in "
+                           "addition to writing them to ${T}/log.do_<task>).")
+
+    parser.add_option("-D", "--debug", action="count", dest="debug", default=0,
+                      help="Increase the debug level. You can specify this "
+                           "more than once. -D sets the debug level to 1, "
+                           "where only bb.debug(1, ...) messages are printed "
+                           "to stdout; -DD sets the debug level to 2, where "
+                           "both bb.debug(1, ...) and bb.debug(2, ...) "
+                           "messages are printed; etc. Without -D, no debug "
+                           "messages are printed. Note that -D only affects "
+                           "output to stdout. All debug messages are written "
+                           "to ${T}/log.do_taskname, regardless of the debug "
+                           "level.")
+
+    parser.add_option("-q", "--quiet", action="count", dest="quiet", default=0,
+                      help="Output less log message data to the terminal. You can specify this more than once.")
+
+    parser.add_option("-n", "--dry-run", action="store_true", dest="dry_run", default=False,
+                      help="Don't execute, just go through the motions.")
+
+    parser.add_option("-S", "--dump-signatures", action="append", dest="dump_signatures",
+                      default=[], metavar="SIGNATURE_HANDLER",
+                      help="Dump out the signature construction information, with no task "
+                           "execution. The SIGNATURE_HANDLER parameter is passed to the "
+                           "handler. Two common values are none and printdiff but the handler "
+                           "may define more/less. none means only dump the signature, printdiff"
+                           " means compare the dumped signature with the cached one.")
+
+    parser.add_option("-p", "--parse-only", action="store_true",
+                      dest="parse_only", default=False,
+                      help="Quit after parsing the BB recipes.")
+
+    parser.add_option("-s", "--show-versions", action="store_true",
+                      dest="show_versions", default=False,
+                      help="Show current and preferred versions of all recipes.")
+
+    parser.add_option("-e", "--environment", action="store_true",
+                      dest="show_environment", default=False,
+                      help="Show the global or per-recipe environment complete with information"
+                           " about where variables were set/changed.")
+
+    parser.add_option("-g", "--graphviz", action="store_true", dest="dot_graph", default=False,
+                      help="Save dependency tree information for the specified "
+                           "targets in the dot syntax.")
+
+    parser.add_option("-I", "--ignore-deps", action="append",
+                      dest="extra_assume_provided", default=[],
+                      help="Assume these dependencies don't exist and are already provided "
+                           "(equivalent to ASSUME_PROVIDED). Useful to make dependency "
+                           "graphs more appealing")
+
+    parser.add_option("-l", "--log-domains", action="append", dest="debug_domains", default=[],
+                      help="Show debug logging for the specified logging domains")
+
+    parser.add_option("-P", "--profile", action="store_true", dest="profile", default=False,
+                      help="Profile the command and save reports.")
+
+    # @CHOICES@ is substituted out by BitbakeHelpFormatter above
+    parser.add_option("-u", "--ui", action="store", dest="ui",
+                      default=os.environ.get('BITBAKE_UI', 'knotty'),
+                      help="The user interface to use (@CHOICES@ - default %default).")
+
+    parser.add_option("", "--token", action="store", dest="xmlrpctoken",
+                      default=os.environ.get("BBTOKEN"),
+                      help="Specify the connection token to be used when connecting "
+                           "to a remote server.")
+
+    parser.add_option("", "--revisions-changed", action="store_true",
+                      dest="revisions_changed", default=False,
+                      help="Set the exit code depending on whether upstream floating "
+                           "revisions have changed or not.")
+
+    parser.add_option("", "--server-only", action="store_true",
+                      dest="server_only", default=False,
+                      help="Run bitbake without a UI, only starting a server "
+                           "(cooker) process.")
+
+    parser.add_option("-B", "--bind", action="store", dest="bind", default=False,
+                      help="The name/address for the bitbake xmlrpc server to bind to.")
+
+    parser.add_option("-T", "--idle-timeout", type=float, dest="server_timeout",
+                      default=os.getenv("BB_SERVER_TIMEOUT"),
+                      help="Set timeout to unload bitbake server due to inactivity, "
+                           "set to -1 means no unload, "
+                           "default: Environment variable BB_SERVER_TIMEOUT.")
+
+    parser.add_option("", "--no-setscene", action="store_true",
+                      dest="nosetscene", default=False,
+                      help="Do not run any setscene tasks. sstate will be ignored and "
+                           "everything needed, built.")
+
+    parser.add_option("", "--skip-setscene", action="store_true",
+                      dest="skipsetscene", default=False,
+                      help="Skip setscene tasks if they would be executed. Tasks previously "
+                           "restored from sstate will be kept, unlike --no-setscene")
+
+    parser.add_option("", "--setscene-only", action="store_true",
+                      dest="setsceneonly", default=False,
+                      help="Only run setscene tasks, don't run any real tasks.")
+
+    parser.add_option("", "--remote-server", action="store", dest="remote_server",
+                      default=os.environ.get("BBSERVER"),
+                      help="Connect to the specified server.")
+
+    parser.add_option("-m", "--kill-server", action="store_true",
+                      dest="kill_server", default=False,
+                      help="Terminate any running bitbake server.")
+
+    parser.add_option("", "--observe-only", action="store_true",
+                      dest="observe_only", default=False,
+                      help="Connect to a server as an observing-only client.")
+
+    parser.add_option("", "--status-only", action="store_true",
+                      dest="status_only", default=False,
+                      help="Check the status of the remote bitbake server.")
+
+    parser.add_option("-w", "--write-log", action="store", dest="writeeventlog",
+                      default=os.environ.get("BBEVENTLOG"),
+                      help="Writes the event log of the build to a bitbake event json file. "
+                           "Use '' (empty string) to assign the name automatically.")
+
+    parser.add_option("", "--runall", action="append", dest="runall",
+                      help="Run the specified task for any recipe in the taskgraph of the specified target (even if it wouldn't otherwise have run).")
+
+    parser.add_option("", "--runonly", action="append", dest="runonly",
+                      help="Run only the specified task within the taskgraph of the specified targets (and any task dependencies those tasks may have).")
+    return parser
 
 
+class BitBakeConfigParameters(cookerdata.ConfigParameters):
+    def parseCommandLine(self, argv=sys.argv):
+        parser = create_bitbake_parser()
         options, targets = parser.parse_args(argv)
 
         if options.quiet and options.verbose:
@@ -344,8 +347,6 @@ def bitbake_main(configParams, configuration):
     except:
         pass
 
-    configuration.setConfigParameters(configParams)
-
     if configParams.server_only and configParams.remote_server:
             raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" %
                                   ("the BBSERVER environment variable" if "BBSERVER" in os.environ \
@@ -357,13 +358,13 @@ def bitbake_main(configParams, configuration):
 
     if "BBDEBUG" in os.environ:
         level = int(os.environ["BBDEBUG"])
-        if level > configuration.debug:
-            configuration.debug = level
+        if level > configParams.debug:
+            configParams.debug = level
 
-    bb.msg.init_msgconfig(configParams.verbose, configuration.debug,
-                          configuration.debug_domains)
+    bb.msg.init_msgconfig(configParams.verbose, configParams.debug,
+                          configParams.debug_domains)
 
-    server_connection, ui_module = setup_bitbake(configParams, configuration)
+    server_connection, ui_module = setup_bitbake(configParams)
     # No server connection
     if server_connection is None:
         if configParams.status_only:
@@ -390,7 +391,7 @@ def bitbake_main(configParams, configuration):
 
     return 1
 
-def setup_bitbake(configParams, configuration, extrafeatures=None):
+def setup_bitbake(configParams, extrafeatures=None):
     # Ensure logging messages get sent to the UI as events
     handler = bb.event.LogHandler()
     if not configParams.status_only:
@@ -431,11 +432,11 @@ def setup_bitbake(configParams, configuration, extrafeatures=None):
                         logger.info("bitbake server is not running.")
                         lock.close()
                         return None, None
-                    # we start a server with a given configuration
+                    # we start a server with a given featureset
                     logger.info("Starting bitbake server...")
                     # Clear the event queue since we already displayed messages
                     bb.event.ui_queue = []
-                    server = bb.server.process.BitBakeServer(lock, sockname, configuration, featureset)
+                    server = bb.server.process.BitBakeServer(lock, sockname, featureset, configParams.server_timeout, configParams.xmlrpcinterface)
 
                 else:
                     logger.info("Reconnecting to bitbake server...")
@@ -458,15 +459,17 @@ def setup_bitbake(configParams, configuration, extrafeatures=None):
                     break
             except BBMainFatal:
                 raise
-            except (Exception, bb.server.process.ProcessTimeout) as e:
+            except (Exception, bb.server.process.ProcessTimeout, SystemExit) as e:
+                # SystemExit does not inherit from the Exception class, needs to be included explicitly
                 if not retries:
                     raise
                 retries -= 1
                 tryno = 8 - retries
-                if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError)):
+                if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError, EOFError, SystemExit)):
                     logger.info("Retrying server connection (#%d)..." % tryno)
                 else:
                     logger.info("Retrying server connection (#%d)... (%s)" % (tryno, traceback.format_exc()))
+
             if not retries:
                 bb.fatal("Unable to connect to bitbake server, or start one (server startup failures would be in bitbake-cookerdaemon.log).")
             bb.event.print_ui_queue()
diff --git a/bitbake/lib/bb/monitordisk.py b/bitbake/lib/bb/monitordisk.py
index e7c07264..98f2109e 100644
--- a/bitbake/lib/bb/monitordisk.py
+++ b/bitbake/lib/bb/monitordisk.py
@@ -59,7 +59,7 @@ def getMountedDev(path):
         pass
     return None
 
-def getDiskData(BBDirs, configuration):
+def getDiskData(BBDirs):
 
     """Prepare disk data for disk space monitor"""
 
@@ -168,7 +168,7 @@ class diskMonitor:
 
         BBDirs = configuration.getVar("BB_DISKMON_DIRS") or None
         if BBDirs:
-            self.devDict = getDiskData(BBDirs, configuration)
+            self.devDict = getDiskData(BBDirs)
             if self.devDict:
                 self.spaceInterval, self.inodeInterval = getInterval(configuration)
                 if self.spaceInterval and self.inodeInterval:
diff --git a/bitbake/lib/bb/msg.py b/bitbake/lib/bb/msg.py
index 2d88c4e7..291b38ff 100644
--- a/bitbake/lib/bb/msg.py
+++ b/bitbake/lib/bb/msg.py
@@ -14,6 +14,7 @@ import sys
 import copy
 import logging
 import logging.config
+import os
 from itertools import groupby
 import bb
 import bb.event
@@ -146,18 +147,12 @@ class LogFilterLTLevel(logging.Filter):
 #
 
 loggerDefaultLogLevel = BBLogFormatter.NOTE
-loggerDefaultVerbose = False
-loggerVerboseLogs = False
 loggerDefaultDomains = {}
 
 def init_msgconfig(verbose, debug, debug_domains=None):
     """
     Set default verbosity and debug levels config the logger
     """
-    bb.msg.loggerDefaultVerbose = verbose
-    if verbose:
-        bb.msg.loggerVerboseLogs = True
-
     if debug:
         bb.msg.loggerDefaultLogLevel = BBLogFormatter.DEBUG - debug + 1
     elif verbose:
@@ -283,7 +278,7 @@ def setLoggingConfig(defaultconfig, userconfigfile=None):
         with open(os.path.normpath(userconfigfile), 'r') as f:
             if userconfigfile.endswith('.yml') or userconfigfile.endswith('.yaml'):
                 import yaml
-                userconfig = yaml.load(f)
+                userconfig = yaml.safe_load(f)
             elif userconfigfile.endswith('.json') or userconfigfile.endswith('.cfg'):
                 import json
                 userconfig = json.load(f)
diff --git a/bitbake/lib/bb/namedtuple_with_abc.py b/bitbake/lib/bb/namedtuple_with_abc.py
index 646aed6f..e46dbf08 100644
--- a/bitbake/lib/bb/namedtuple_with_abc.py
+++ b/bitbake/lib/bb/namedtuple_with_abc.py
@@ -61,17 +61,9 @@ class _NamedTupleABCMeta(ABCMeta):
         return ABCMeta.__new__(mcls, name, bases, namespace)
 
 
-exec(
-    # Python 2.x metaclass declaration syntax
-    """class _NamedTupleABC(object):
-        '''The abstract base class + mix-in for named tuples.'''
-        __metaclass__ = _NamedTupleABCMeta
-        _fields = abstractproperty()""" if version_info[0] < 3 else
-    # Python 3.x metaclass declaration syntax
-    """class _NamedTupleABC(metaclass=_NamedTupleABCMeta):
-        '''The abstract base class + mix-in for named tuples.'''
-        _fields = abstractproperty()"""
-)
+class _NamedTupleABC(metaclass=_NamedTupleABCMeta):
+    '''The abstract base class + mix-in for named tuples.'''
+    _fields = abstractproperty()
 
 
 _namedtuple.abc = _NamedTupleABC
diff --git a/bitbake/lib/bb/parse/__init__.py b/bitbake/lib/bb/parse/__init__.py
index 76e180b4..c01807ba 100644
--- a/bitbake/lib/bb/parse/__init__.py
+++ b/bitbake/lib/bb/parse/__init__.py
@@ -71,7 +71,7 @@ def update_mtime(f):
 
 def update_cache(f):
     if f in __mtime_cache:
-        logger.debug(1, "Updating mtime cache for %s" % f)
+        logger.debug("Updating mtime cache for %s" % f)
         update_mtime(f)
 
 def clear_cache():
diff --git a/bitbake/lib/bb/parse/ast.py b/bitbake/lib/bb/parse/ast.py
index eb8cfa21..db2bdc35 100644
--- a/bitbake/lib/bb/parse/ast.py
+++ b/bitbake/lib/bb/parse/ast.py
@@ -34,7 +34,7 @@ class IncludeNode(AstNode):
         Include the file and evaluate the statements
         """
         s = data.expand(self.what_file)
-        logger.debug(2, "CONF %s:%s: including %s", self.filename, self.lineno, s)
+        logger.debug2("CONF %s:%s: including %s", self.filename, self.lineno, s)
 
         # TODO: Cache those includes... maybe not here though
         if self.force:
@@ -97,6 +97,7 @@ class DataNode(AstNode):
     def eval(self, data):
         groupd = self.groupd
         key = groupd["var"]
+        key = key.replace(":", "_")
         loginfo = {
             'variable': key,
             'file': self.filename,
@@ -207,6 +208,7 @@ class ExportFuncsNode(AstNode):
     def eval(self, data):
 
         for func in self.n:
+            func = func.replace(":", "_")
             calledfunc = self.classname + "_" + func
 
             if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False):
@@ -244,12 +246,14 @@ class AddTaskNode(AstNode):
         bb.build.addtask(self.func, self.before, self.after, data)
 
 class DelTaskNode(AstNode):
-    def __init__(self, filename, lineno, func):
+    def __init__(self, filename, lineno, tasks):
         AstNode.__init__(self, filename, lineno)
-        self.func = func
+        self.tasks = tasks
 
     def eval(self, data):
-        bb.build.deltask(self.func, data)
+        tasks = data.expand(self.tasks).split()
+        for task in tasks:
+            bb.build.deltask(task, data)
 
 class BBHandlerNode(AstNode):
     def __init__(self, filename, lineno, fns):
@@ -305,7 +309,7 @@ def handleAddTask(statements, filename, lineno, m):
     statements.append(AddTaskNode(filename, lineno, func, before, after))
 
 def handleDelTask(statements, filename, lineno, m):
-    func = m.group("func")
+    func = m.group(1)
     if func is None:
         return
 
@@ -333,11 +337,14 @@ def finalize(fn, d, variant = None):
             if not handlerfn:
                 bb.fatal("Undefined event handler function '%s'" % var)
             handlerln = int(d.getVarFlag(var, "lineno", False))
-            bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln)
+            bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask") or "").split(), handlerfn, handlerln, data=d)
 
         bb.event.fire(bb.event.RecipePreFinalise(fn), d)
 
         bb.data.expandKeys(d)
+
+        bb.event.fire(bb.event.RecipePostKeyExpansion(fn), d)
+
         runAnonFuncs(d)
 
         tasklist = d.getVar('__BBTASKS', False) or []
@@ -371,7 +378,7 @@ def _create_variants(datastores, names, function, onlyfinalise):
 def multi_finalize(fn, d):
     appends = (d.getVar("__BBAPPEND") or "").split()
     for append in appends:
-        logger.debug(1, "Appending .bbappend file %s to %s", append, fn)
+        logger.debug("Appending .bbappend file %s to %s", append, fn)
         bb.parse.BBHandler.handle(append, d, True)
 
     onlyfinalise = d.getVar("__ONLYFINALISE", False)
diff --git a/bitbake/lib/bb/parse/parse_py/BBHandler.py b/bitbake/lib/bb/parse/parse_py/BBHandler.py
index 6e216eff..152ef6ab 100644
--- a/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -13,7 +13,7 @@
 #
 
 import re, bb, os
-import bb.build, bb.utils
+import bb.build, bb.utils, bb.data_smart
 
 from . import ConfHandler
 from .. import resolve_file, ast, logger, ParseError
@@ -22,11 +22,11 @@ from .ConfHandler import include, init
 # For compatibility
 bb.deprecate_import(__name__, "bb.parse", ["vars_from_file"])
 
-__func_start_regexp__    = re.compile(r"(((?P<py>python)|(?P<fr>fakeroot))\s*)*(?P<func>[\w\.\-\+\{\}\$]+)?\s*\(\s*\)\s*{$" )
+__func_start_regexp__    = re.compile(r"(((?P<py>python(?=(\s|\()))|(?P<fr>fakeroot(?=\s)))\s*)*(?P<func>[\w\.\-\+\{\}\$:]+)?\s*\(\s*\)\s*{$" )
 __inherit_regexp__       = re.compile(r"inherit\s+(.+)" )
 __export_func_regexp__   = re.compile(r"EXPORT_FUNCTIONS\s+(.+)" )
 __addtask_regexp__       = re.compile(r"addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
-__deltask_regexp__       = re.compile(r"deltask\s+(?P<func>\w+)(?P<ignores>.*)")
+__deltask_regexp__       = re.compile(r"deltask\s+(.+)")
 __addhandler_regexp__    = re.compile(r"addhandler\s+(.+)" )
 __def_regexp__           = re.compile(r"def\s+(\w+).*:" )
 __python_func_regexp__   = re.compile(r"(\s+.*)|(^$)|(^#)" )
@@ -60,7 +60,7 @@ def inherit(files, fn, lineno, d):
                 file = abs_fn
 
         if not file in __inherit_cache:
-            logger.debug(1, "Inheriting %s (from %s:%d)" % (file, fn, lineno))
+            logger.debug("Inheriting %s (from %s:%d)" % (file, fn, lineno))
             __inherit_cache.append( file )
             d.setVar('__inherit_cache', __inherit_cache)
             include(fn, file, lineno, d, "inherit")
@@ -233,14 +233,15 @@ def feeder(lineno, s, fn, root, statements, eof=False):
             if taskexpression.count(word) > 1:
                 logger.warning("addtask contained multiple '%s' keywords, only one is supported" % word)
 
+        # Check and warn for having task with exprssion as part of task name
+        for te in taskexpression:
+            if any( ( "%s_" % keyword ) in te for keyword in bb.data_smart.__setvar_keyword__ ):
+                raise ParseError("Task name '%s' contains a keyword which is not recommended/supported.\nPlease rename the task not to include the keyword.\n%s" % (te, ("\n".join(map(str, bb.data_smart.__setvar_keyword__)))), fn)
         ast.handleAddTask(statements, fn, lineno, m)
         return
 
     m = __deltask_regexp__.match(s)
     if m:
-        # Check and warn "for deltask task1 task2"
-        if m.group('ignores'):
-            logger.warning('deltask ignored: "%s"' % m.group('ignores'))
         ast.handleDelTask(statements, fn, lineno, m)
         return
 
diff --git a/bitbake/lib/bb/parse/parse_py/ConfHandler.py b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
index af64d344..0834fe3f 100644
--- a/bitbake/lib/bb/parse/parse_py/ConfHandler.py
+++ b/bitbake/lib/bb/parse/parse_py/ConfHandler.py
@@ -20,7 +20,7 @@ from bb.parse import ParseError, resolve_file, ast, logger, handle
 __config_regexp__  = re.compile( r"""
     ^
     (?P<exp>export\s+)?
-    (?P<var>[a-zA-Z0-9\-_+.${}/~]+?)
+    (?P<var>[a-zA-Z0-9\-_+.${}/~:]+?)
     (\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?
 
     \s* (
@@ -95,7 +95,7 @@ def include_single_file(parentfn, fn, lineno, data, error_out):
         if exc.errno == errno.ENOENT:
             if error_out:
                 raise ParseError("Could not %s file %s" % (error_out, fn), parentfn, lineno)
-            logger.debug(2, "CONF file '%s' not found", fn)
+            logger.debug2("CONF file '%s' not found", fn)
         else:
             if error_out:
                 raise ParseError("Could not %s file %s: %s" % (error_out, fn, exc.strerror), parentfn, lineno)
diff --git a/bitbake/lib/bb/persist_data.py b/bitbake/lib/bb/persist_data.py
index 7357ab2d..c6a209fb 100644
--- a/bitbake/lib/bb/persist_data.py
+++ b/bitbake/lib/bb/persist_data.py
@@ -12,14 +12,14 @@ currently, providing a key/value store accessed by 'domain'.
 #
 
 import collections
+import contextlib
+import functools
 import logging
 import os.path
+import sqlite3
 import sys
 import warnings
-from bb.compat import total_ordering
 from collections import Mapping
-import sqlite3
-import contextlib
 
 sqlversion = sqlite3.sqlite_version_info
 if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
@@ -28,7 +28,7 @@ if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
 
 logger = logging.getLogger("BitBake.PersistData")
 
-@total_ordering
+@functools.total_ordering
 class SQLTable(collections.MutableMapping):
     class _Decorators(object):
         @staticmethod
@@ -248,7 +248,7 @@ class PersistData(object):
                       stacklevel=2)
 
         self.data = persist(d)
-        logger.debug(1, "Using '%s' as the persistent data cache",
+        logger.debug("Using '%s' as the persistent data cache",
                      self.data.filename)
 
     def addDomain(self, domain):
diff --git a/bitbake/lib/bb/process.py b/bitbake/lib/bb/process.py
index 2dc472a8..d5a1775f 100644
--- a/bitbake/lib/bb/process.py
+++ b/bitbake/lib/bb/process.py
@@ -7,6 +7,7 @@ import signal
 import subprocess
 import errno
 import select
+import bb
 
 logger = logging.getLogger('BitBake.Process')
 
@@ -41,6 +42,7 @@ class ExecutionError(CmdError):
         self.exitcode = exitcode
         self.stdout = stdout
         self.stderr = stderr
+        self.extra_message = None
 
     def __str__(self):
         message = ""
@@ -51,7 +53,7 @@ class ExecutionError(CmdError):
         if message:
             message = ":\n" + message
         return (CmdError.__str__(self) +
-                " with exit code %s" % self.exitcode + message)
+                " with exit code %s" % self.exitcode + message + (self.extra_message or ""))
 
 class Popen(subprocess.Popen):
     defaults = {
@@ -179,5 +181,8 @@ def run(cmd, input=None, log=None, extrafiles=None, **options):
             stderr = stderr.decode("utf-8")
 
     if pipe.returncode != 0:
+        if log:
+            # Don't duplicate the output in the exception if logging it
+            raise ExecutionError(cmd, pipe.returncode, None, None)
         raise ExecutionError(cmd, pipe.returncode, stdout, stderr)
     return stdout, stderr
diff --git a/bitbake/lib/bb/progress.py b/bitbake/lib/bb/progress.py
index 9c755b7f..d051ba01 100644
--- a/bitbake/lib/bb/progress.py
+++ b/bitbake/lib/bb/progress.py
@@ -14,7 +14,27 @@ import bb.event
 import bb.build
 from bb.build import StdoutNoopContextManager
 
-class ProgressHandler(object):
+
+# from https://stackoverflow.com/a/14693789/221061
+ANSI_ESCAPE_REGEX = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
+
+
+def filter_color(string):
+    """
+    Filter ANSI escape codes out of |string|, return new string
+    """
+    return ANSI_ESCAPE_REGEX.sub('', string)
+
+
+def filter_color_n(string):
+    """
+    Filter ANSI escape codes out of |string|, returns tuple of
+    (new string, # of ANSI codes removed)
+    """
+    return ANSI_ESCAPE_REGEX.subn('', string)
+
+
+class ProgressHandler:
     """
     Base class that can pretend to be a file object well enough to be
     used to build objects to intercept console output and determine the
@@ -55,6 +75,7 @@ class ProgressHandler(object):
             self._lastevent = ts
             self._progress = progress
 
+
 class LineFilterProgressHandler(ProgressHandler):
     """
     A ProgressHandler variant that provides the ability to filter out
@@ -66,7 +87,7 @@ class LineFilterProgressHandler(ProgressHandler):
     """
     def __init__(self, d, outfile=None):
         self._linebuffer = ''
-        super(LineFilterProgressHandler, self).__init__(d, outfile)
+        super().__init__(d, outfile)
 
     def write(self, string):
         self._linebuffer += string
@@ -80,41 +101,44 @@ class LineFilterProgressHandler(ProgressHandler):
             lbreakpos = line.rfind('\r') + 1
             if lbreakpos:
                 line = line[lbreakpos:]
-            if self.writeline(line):
-                super(LineFilterProgressHandler, self).write(line)
+            if self.writeline(filter_color(line)):
+                super().write(line)
 
     def writeline(self, line):
         return True
 
+
 class BasicProgressHandler(ProgressHandler):
     def __init__(self, d, regex=r'(\d+)%', outfile=None):
-        super(BasicProgressHandler, self).__init__(d, outfile)
+        super().__init__(d, outfile)
         self._regex = re.compile(regex)
         # Send an initial progress event so the bar gets shown
         self._fire_progress(0)
 
     def write(self, string):
-        percs = self._regex.findall(string)
+        percs = self._regex.findall(filter_color(string))
         if percs:
             progress = int(percs[-1])
             self.update(progress)
-        super(BasicProgressHandler, self).write(string)
+        super().write(string)
+
 
 class OutOfProgressHandler(ProgressHandler):
     def __init__(self, d, regex, outfile=None):
-        super(OutOfProgressHandler, self).__init__(d, outfile)
+        super().__init__(d, outfile)
         self._regex = re.compile(regex)
         # Send an initial progress event so the bar gets shown
         self._fire_progress(0)
 
     def write(self, string):
-        nums = self._regex.findall(string)
+        nums = self._regex.findall(filter_color(string))
         if nums:
             progress = (float(nums[-1][0]) / float(nums[-1][1])) * 100
             self.update(progress)
-        super(OutOfProgressHandler, self).write(string)
+        super().write(string)
+
 
-class MultiStageProgressReporter(object):
+class MultiStageProgressReporter:
     """
     Class which allows reporting progress without the caller
     having to know where they are in the overall sequence. Useful
@@ -199,6 +223,7 @@ class MultiStageProgressReporter(object):
           value is considered to be out of stage_total, otherwise it should
           be a percentage value from 0 to 100.
         """
+        progress = None
         if self._stage_total:
             stage_progress = (float(stage_progress) / self._stage_total) * 100
         if self._stage < 0:
@@ -207,9 +232,10 @@ class MultiStageProgressReporter(object):
             progress = self._base_progress + (stage_progress * self._stage_weights[self._stage])
         else:
             progress = self._base_progress
-        if progress > 100:
-            progress = 100
-        self._fire_progress(progress)
+        if progress:
+            if progress > 100:
+                progress = 100
+            self._fire_progress(progress)
 
     def finish(self):
         if self._finished:
@@ -230,6 +256,7 @@ class MultiStageProgressReporter(object):
                     out.append('Up to finish: %d' % stage_weight)
             bb.warn('Stage times:\n  %s' % '\n  '.join(out))
 
+
 class MultiStageProcessProgressReporter(MultiStageProgressReporter):
     """
     Version of MultiStageProgressReporter intended for use with
@@ -238,7 +265,7 @@ class MultiStageProcessProgressReporter(MultiStageProgressReporter):
     def __init__(self, d, processname, stage_weights, debug=False):
         self._processname = processname
         self._started = False
-        MultiStageProgressReporter.__init__(self, d, stage_weights, debug)
+        super().__init__(d, stage_weights, debug)
 
     def start(self):
         if not self._started:
@@ -255,13 +282,14 @@ class MultiStageProcessProgressReporter(MultiStageProgressReporter):
         MultiStageProgressReporter.finish(self)
         bb.event.fire(bb.event.ProcessFinished(self._processname), self._data)
 
+
 class DummyMultiStageProcessProgressReporter(MultiStageProgressReporter):
     """
     MultiStageProcessProgressReporter that takes the calls and does nothing
     with them (to avoid a bunch of "if progress_reporter:" checks)
     """
     def __init__(self):
-        MultiStageProcessProgressReporter.__init__(self, "", None, [])
+        super().__init__(None, [])
 
     def _fire_progress(self, taskprogress, rate=None):
         pass
diff --git a/bitbake/lib/bb/providers.py b/bitbake/lib/bb/providers.py
index 81459c36..3ec11a40 100644
--- a/bitbake/lib/bb/providers.py
+++ b/bitbake/lib/bb/providers.py
@@ -38,16 +38,17 @@ def findProviders(cfgData, dataCache, pkg_pn = None):
     localdata = data.createCopy(cfgData)
     bb.data.expandKeys(localdata)
 
+    required = {}
     preferred_versions = {}
     latest_versions = {}
 
     for pn in pkg_pn:
-        (last_ver, last_file, pref_ver, pref_file) = findBestProvider(pn, localdata, dataCache, pkg_pn)
+        (last_ver, last_file, pref_ver, pref_file, req) = findBestProvider(pn, localdata, dataCache, pkg_pn)
         preferred_versions[pn] = (pref_ver, pref_file)
         latest_versions[pn] = (last_ver, last_file)
+        required[pn] = req
 
-    return (latest_versions, preferred_versions)
-
+    return (latest_versions, preferred_versions, required)
 
 def allProviders(dataCache):
     """
@@ -59,7 +60,6 @@ def allProviders(dataCache):
         all_providers[pn].append((ver, fn))
     return all_providers
 
-
 def sortPriorities(pn, dataCache, pkg_pn = None):
     """
     Reorder pkg_pn by file priority and default preference
@@ -87,6 +87,21 @@ def sortPriorities(pn, dataCache, pkg_pn = None):
 
     return tmp_pn
 
+def versionVariableMatch(cfgData, keyword, pn):
+    """
+    Return the value of the <keyword>_VERSION variable if set.
+    """
+
+    # pn can contain '_', e.g. gcc-cross-x86_64 and an override cannot
+    # hence we do this manually rather than use OVERRIDES
+    ver = cfgData.getVar("%s_VERSION_pn-%s" % (keyword, pn))
+    if not ver:
+        ver = cfgData.getVar("%s_VERSION_%s" % (keyword, pn))
+    if not ver:
+        ver = cfgData.getVar("%s_VERSION" % keyword)
+
+    return ver
+
 def preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
     """
     Check if the version pe,pv,pr is the preferred one.
@@ -102,19 +117,28 @@ def preferredVersionMatch(pe, pv, pr, preferred_e, preferred_v, preferred_r):
 
 def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
     """
-    Find the first provider in pkg_pn with a PREFERRED_VERSION set.
+    Find the first provider in pkg_pn with REQUIRED_VERSION or PREFERRED_VERSION set.
     """
 
     preferred_file = None
     preferred_ver = None
+    required = False
 
-    # pn can contain '_', e.g. gcc-cross-x86_64 and an override cannot
-    # hence we do this manually rather than use OVERRIDES
-    preferred_v = cfgData.getVar("PREFERRED_VERSION_pn-%s" % pn)
-    if not preferred_v:
-        preferred_v = cfgData.getVar("PREFERRED_VERSION_%s" % pn)
-    if not preferred_v:
-        preferred_v = cfgData.getVar("PREFERRED_VERSION")
+    required_v = versionVariableMatch(cfgData, "REQUIRED", pn)
+    preferred_v = versionVariableMatch(cfgData, "PREFERRED", pn)
+
+    itemstr = ""
+    if item:
+        itemstr = " (for item %s)" % item
+
+    if required_v is not None:
+        if preferred_v is not None:
+            logger.warn("REQUIRED_VERSION and PREFERRED_VERSION for package %s%s are both set using REQUIRED_VERSION %s", pn, itemstr, required_v)
+        else:
+            logger.debug("REQUIRED_VERSION is set for package %s%s", pn, itemstr)
+        # REQUIRED_VERSION always takes precedence over PREFERRED_VERSION
+        preferred_v = required_v
+        required = True
 
     if preferred_v:
         m = re.match(r'(\d+:)*(.*)(_.*)*', preferred_v)
@@ -147,11 +171,9 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
             pv_str = preferred_v
         if not (preferred_e is None):
             pv_str = '%s:%s' % (preferred_e, pv_str)
-        itemstr = ""
-        if item:
-            itemstr = " (for item %s)" % item
         if preferred_file is None:
-            logger.info("preferred version %s of %s not available%s", pv_str, pn, itemstr)
+            if not required:
+                logger.warn("preferred version %s of %s not available%s", pv_str, pn, itemstr)
             available_vers = []
             for file_set in pkg_pn:
                 for f in file_set:
@@ -163,12 +185,16 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
                         available_vers.append(ver_str)
             if available_vers:
                 available_vers.sort()
-                logger.info("versions of %s available: %s", pn, ' '.join(available_vers))
+                logger.warn("versions of %s available: %s", pn, ' '.join(available_vers))
+            if required:
+                logger.error("required version %s of %s not available%s", pv_str, pn, itemstr)
         else:
-            logger.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr)
-
-    return (preferred_ver, preferred_file)
+            if required:
+                logger.debug("selecting %s as REQUIRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr)
+            else:
+                logger.debug("selecting %s as PREFERRED_VERSION %s of package %s%s", preferred_file, pv_str, pn, itemstr)
 
+    return (preferred_ver, preferred_file, required)
 
 def findLatestProvider(pn, cfgData, dataCache, file_set):
     """
@@ -189,7 +215,6 @@ def findLatestProvider(pn, cfgData, dataCache, file_set):
 
     return (latest, latest_f)
 
-
 def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
     """
     If there is a PREFERRED_VERSION, find the highest-priority bbfile
@@ -198,17 +223,16 @@ def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
     """
 
     sortpkg_pn = sortPriorities(pn, dataCache, pkg_pn)
-    # Find the highest priority provider with a PREFERRED_VERSION set
-    (preferred_ver, preferred_file) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item)
+    # Find the highest priority provider with a REQUIRED_VERSION or PREFERRED_VERSION set
+    (preferred_ver, preferred_file, required) = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn, item)
     # Find the latest version of the highest priority provider
     (latest, latest_f) = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[0])
 
-    if preferred_file is None:
+    if not required and preferred_file is None:
         preferred_file = latest_f
         preferred_ver = latest
 
-    return (latest, latest_f, preferred_ver, preferred_file)
-
+    return (latest, latest_f, preferred_ver, preferred_file, required)
 
 def _filterProviders(providers, item, cfgData, dataCache):
     """
@@ -232,12 +256,15 @@ def _filterProviders(providers, item, cfgData, dataCache):
             pkg_pn[pn] = []
         pkg_pn[pn].append(p)
 
-    logger.debug(1, "providers for %s are: %s", item, list(sorted(pkg_pn.keys())))
+    logger.debug("providers for %s are: %s", item, list(sorted(pkg_pn.keys())))
 
-    # First add PREFERRED_VERSIONS
+    # First add REQUIRED_VERSIONS or PREFERRED_VERSIONS
     for pn in sorted(pkg_pn):
         sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn)
-        preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
+        preferred_ver, preferred_file, required = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
+        if required and preferred_file is None:
+            return eligible
+        preferred_versions[pn] = (preferred_ver, preferred_file)
         if preferred_versions[pn][1]:
             eligible.append(preferred_versions[pn][1])
 
@@ -248,9 +275,8 @@ def _filterProviders(providers, item, cfgData, dataCache):
         preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0])
         eligible.append(preferred_versions[pn][1])
 
-    if len(eligible) == 0:
-        logger.error("no eligible providers for %s", item)
-        return 0
+    if not eligible:
+        return eligible
 
     # If pn == item, give it a slight default preference
     # This means PREFERRED_PROVIDER_foobar defaults to foobar if available
@@ -266,7 +292,6 @@ def _filterProviders(providers, item, cfgData, dataCache):
 
     return eligible
 
-
 def filterProviders(providers, item, cfgData, dataCache):
     """
     Take a list of providers and filter/reorder according to the
@@ -291,7 +316,7 @@ def filterProviders(providers, item, cfgData, dataCache):
                 foundUnique = True
                 break
 
-    logger.debug(1, "sorted providers for %s are: %s", item, eligible)
+    logger.debug("sorted providers for %s are: %s", item, eligible)
 
     return eligible, foundUnique
 
@@ -333,7 +358,7 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
             provides = dataCache.pn_provides[pn]
             for provide in provides:
                 prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide)
-                #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
+                #logger.debug("checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
                 if prefervar in pns and pns[prefervar] not in preferred:
                     var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
                     logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
@@ -349,7 +374,7 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
     if numberPreferred > 1:
         logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s. You could set PREFERRED_RPROVIDER_%s" % (item, preferred, preferred_vars, item))
 
-    logger.debug(1, "sorted runtime providers for %s are: %s", item, eligible)
+    logger.debug("sorted runtime providers for %s are: %s", item, eligible)
 
     return eligible, numberPreferred
 
@@ -384,11 +409,10 @@ def getRuntimeProviders(dataCache, rdepend):
             regexp_cache[pattern] = regexp
         if regexp.match(rdepend):
             rproviders += dataCache.packages_dynamic[pattern]
-            logger.debug(1, "Assuming %s is a dynamic package, but it may not exist" % rdepend)
+            logger.debug("Assuming %s is a dynamic package, but it may not exist" % rdepend)
 
     return rproviders
 
-
 def buildWorldTargetList(dataCache, task=None):
     """
     Build package list for "bitbake world"
@@ -396,22 +420,22 @@ def buildWorldTargetList(dataCache, task=None):
     if dataCache.world_target:
         return
 
-    logger.debug(1, "collating packages for \"world\"")
+    logger.debug("collating packages for \"world\"")
     for f in dataCache.possible_world:
         terminal = True
         pn = dataCache.pkg_fn[f]
         if task and task not in dataCache.task_deps[f]['tasks']:
-            logger.debug(2, "World build skipping %s as task %s doesn't exist", f, task)
+            logger.debug2("World build skipping %s as task %s doesn't exist", f, task)
             terminal = False
 
         for p in dataCache.pn_provides[pn]:
             if p.startswith('virtual/'):
-                logger.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
+                logger.debug2("World build skipping %s due to %s provider starting with virtual/", f, p)
                 terminal = False
                 break
             for pf in dataCache.providers[p]:
                 if dataCache.pkg_fn[pf] != pn:
-                    logger.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
+                    logger.debug2("World build skipping %s due to both us and %s providing %s", f, pf, p)
                     terminal = False
                     break
         if terminal:
diff --git a/bitbake/lib/bb/runqueue.py b/bitbake/lib/bb/runqueue.py
index 30cab537..10511a09 100644
--- a/bitbake/lib/bb/runqueue.py
+++ b/bitbake/lib/bb/runqueue.py
@@ -38,7 +38,7 @@ def taskname_from_tid(tid):
     return tid.rsplit(":", 1)[1]
 
 def mc_from_tid(tid):
-    if tid.startswith('mc:'):
+    if tid.startswith('mc:') and tid.count(':') >= 2:
         return tid.split(':')[1]
     return ""
 
@@ -46,8 +46,14 @@ def split_tid(tid):
     (mc, fn, taskname, _) = split_tid_mcfn(tid)
     return (mc, fn, taskname)
 
+def split_mc(n):
+    if n.startswith("mc:") and n.count(':') >= 2:
+        _, mc, n = n.split(":", 2)
+        return (mc, n)
+    return ('', n)
+
 def split_tid_mcfn(tid):
-    if tid.startswith('mc:'):
+    if tid.startswith('mc:') and tid.count(':') >= 2:
         elems = tid.split(':')
         mc = elems[1]
         fn = ":".join(elems[2:-1])
@@ -79,15 +85,19 @@ class RunQueueStats:
     """
     Holds statistics on the tasks handled by the associated runQueue
     """
-    def __init__(self, total):
+    def __init__(self, total, setscene_total):
         self.completed = 0
         self.skipped = 0
         self.failed = 0
         self.active = 0
+        self.setscene_active = 0
+        self.setscene_covered = 0
+        self.setscene_notcovered = 0
+        self.setscene_total = setscene_total
         self.total = total
 
     def copy(self):
-        obj = self.__class__(self.total)
+        obj = self.__class__(self.total, self.setscene_total)
         obj.__dict__.update(self.__dict__)
         return obj
 
@@ -106,6 +116,13 @@ class RunQueueStats:
     def taskActive(self):
         self.active = self.active + 1
 
+    def updateCovered(self, covered, notcovered):
+        self.setscene_covered = covered
+        self.setscene_notcovered = notcovered
+
+    def updateActiveSetscene(self, active):
+        self.setscene_active = active
+
 # These values indicate the next step due to be run in the
 # runQueue state machine
 runQueuePrepare = 2
@@ -370,7 +387,7 @@ class RunQueueData:
 
         self.stampwhitelist = cfgData.getVar("BB_STAMP_WHITELIST") or ""
         self.multi_provider_whitelist = (cfgData.getVar("MULTI_PROVIDER_WHITELIST") or "").split()
-        self.setscenewhitelist = get_setscene_enforce_whitelist(cfgData)
+        self.setscenewhitelist = get_setscene_enforce_whitelist(cfgData, targets)
         self.setscenewhitelist_checked = False
         self.setscene_enforce = (cfgData.getVar('BB_SETSCENE_ENFORCE') == "1")
         self.init_progress_reporter = bb.progress.DummyMultiStageProcessProgressReporter()
@@ -538,8 +555,8 @@ class RunQueueData:
         for tid in self.runtaskentries:
             if task_done[tid] is False or deps_left[tid] != 0:
                 problem_tasks.append(tid)
-                logger.debug(2, "Task %s is not buildable", tid)
-                logger.debug(2, "(Complete marker was %s and the remaining dependency count was %s)\n", task_done[tid], deps_left[tid])
+                logger.debug2("Task %s is not buildable", tid)
+                logger.debug2("(Complete marker was %s and the remaining dependency count was %s)\n", task_done[tid], deps_left[tid])
             self.runtaskentries[tid].weight = weight[tid]
 
         if problem_tasks:
@@ -637,7 +654,7 @@ class RunQueueData:
                 (mc, fn, taskname, taskfn) = split_tid_mcfn(tid)
                 #runtid = build_tid(mc, fn, taskname)
 
-                #logger.debug(2, "Processing %s,%s:%s", mc, fn, taskname)
+                #logger.debug2("Processing %s,%s:%s", mc, fn, taskname)
 
                 depends = set()
                 task_deps = self.dataCaches[mc].task_deps[taskfn]
@@ -1184,17 +1201,18 @@ class RunQueueData:
         return len(self.runtaskentries)
 
     def prepare_task_hash(self, tid):
-        bb.parse.siggen.prep_taskhash(tid, self.runtaskentries[tid].depends, self.dataCaches[mc_from_tid(tid)])
-        self.runtaskentries[tid].hash = bb.parse.siggen.get_taskhash(tid, self.runtaskentries[tid].depends, self.dataCaches[mc_from_tid(tid)])
+        dc = bb.parse.siggen.get_data_caches(self.dataCaches, mc_from_tid(tid))
+        bb.parse.siggen.prep_taskhash(tid, self.runtaskentries[tid].depends, dc)
+        self.runtaskentries[tid].hash = bb.parse.siggen.get_taskhash(tid, self.runtaskentries[tid].depends, dc)
         self.runtaskentries[tid].unihash = bb.parse.siggen.get_unihash(tid)
 
     def dump_data(self):
         """
         Dump some debug information on the internal data structures
         """
-        logger.debug(3, "run_tasks:")
+        logger.debug3("run_tasks:")
         for tid in self.runtaskentries:
-            logger.debug(3, " %s: %s   Deps %s RevDeps %s", tid,
+            logger.debug3(" %s: %s   Deps %s RevDeps %s", tid,
                          self.runtaskentries[tid].weight,
                          self.runtaskentries[tid].depends,
                          self.runtaskentries[tid].revdeps)
@@ -1231,10 +1249,11 @@ class RunQueue:
         self.fakeworker = {}
 
     def _start_worker(self, mc, fakeroot = False, rqexec = None):
-        logger.debug(1, "Starting bitbake-worker")
+        logger.debug("Starting bitbake-worker")
         magic = "decafbad"
         if self.cooker.configuration.profile:
             magic = "decafbadbad"
+        fakerootlogs = None
         if fakeroot:
             magic = magic + "beef"
             mcdata = self.cooker.databuilder.mcdata[mc]
@@ -1244,10 +1263,11 @@ class RunQueue:
             for key, value in (var.split('=') for var in fakerootenv):
                 env[key] = value
             worker = subprocess.Popen(fakerootcmd + ["bitbake-worker", magic], stdout=subprocess.PIPE, stdin=subprocess.PIPE, env=env)
+            fakerootlogs = self.rqdata.dataCaches[mc].fakerootlogs
         else:
             worker = subprocess.Popen(["bitbake-worker", magic], stdout=subprocess.PIPE, stdin=subprocess.PIPE)
         bb.utils.nonblockingfd(worker.stdout)
-        workerpipe = runQueuePipe(worker.stdout, None, self.cfgData, self, rqexec)
+        workerpipe = runQueuePipe(worker.stdout, None, self.cfgData, self, rqexec, fakerootlogs=fakerootlogs)
 
         workerdata = {
             "taskdeps" : self.rqdata.dataCaches[mc].task_deps,
@@ -1256,14 +1276,15 @@ class RunQueue:
             "fakerootnoenv" : self.rqdata.dataCaches[mc].fakerootnoenv,
             "sigdata" : bb.parse.siggen.get_taskdata(),
             "logdefaultlevel" : bb.msg.loggerDefaultLogLevel,
-            "logdefaultverbose" : bb.msg.loggerDefaultVerbose,
-            "logdefaultverboselogs" : bb.msg.loggerVerboseLogs,
+            "build_verbose_shell" : self.cooker.configuration.build_verbose_shell,
+            "build_verbose_stdout" : self.cooker.configuration.build_verbose_stdout,
             "logdefaultdomain" : bb.msg.loggerDefaultDomains,
             "prhost" : self.cooker.prhost,
             "buildname" : self.cfgData.getVar("BUILDNAME"),
             "date" : self.cfgData.getVar("DATE"),
             "time" : self.cfgData.getVar("TIME"),
             "hashservaddr" : self.cooker.hashservaddr,
+            "umask" : self.cfgData.getVar("BB_DEFAULT_UMASK"),
         }
 
         worker.stdin.write(b"<cookerconfig>" + pickle.dumps(self.cooker.configuration) + b"</cookerconfig>")
@@ -1276,7 +1297,7 @@ class RunQueue:
     def _teardown_worker(self, worker):
         if not worker:
             return
-        logger.debug(1, "Teardown for bitbake-worker")
+        logger.debug("Teardown for bitbake-worker")
         try:
            worker.process.stdin.write(b"<quit></quit>")
            worker.process.stdin.flush()
@@ -1349,12 +1370,12 @@ class RunQueue:
 
         # If the stamp is missing, it's not current
         if not os.access(stampfile, os.F_OK):
-            logger.debug(2, "Stampfile %s not available", stampfile)
+            logger.debug2("Stampfile %s not available", stampfile)
             return False
         # If it's a 'nostamp' task, it's not current
         taskdep = self.rqdata.dataCaches[mc].task_deps[taskfn]
         if 'nostamp' in taskdep and taskname in taskdep['nostamp']:
-            logger.debug(2, "%s.%s is nostamp\n", fn, taskname)
+            logger.debug2("%s.%s is nostamp\n", fn, taskname)
             return False
 
         if taskname != "do_setscene" and taskname.endswith("_setscene"):
@@ -1378,18 +1399,18 @@ class RunQueue:
                     continue
                 if fn == fn2 or (fulldeptree and fn2 not in stampwhitelist):
                     if not t2:
-                        logger.debug(2, 'Stampfile %s does not exist', stampfile2)
+                        logger.debug2('Stampfile %s does not exist', stampfile2)
                         iscurrent = False
                         break
                     if t1 < t2:
-                        logger.debug(2, 'Stampfile %s < %s', stampfile, stampfile2)
+                        logger.debug2('Stampfile %s < %s', stampfile, stampfile2)
                         iscurrent = False
                         break
                     if recurse and iscurrent:
                         if dep in cache:
                             iscurrent = cache[dep]
                             if not iscurrent:
-                                logger.debug(2, 'Stampfile for dependency %s:%s invalid (cached)' % (fn2, taskname2))
+                                logger.debug2('Stampfile for dependency %s:%s invalid (cached)' % (fn2, taskname2))
                         else:
                             iscurrent = self.check_stamp_task(dep, recurse=True, cache=cache)
                             cache[dep] = iscurrent
@@ -1459,7 +1480,7 @@ class RunQueue:
             if not self.dm_event_handler_registered:
                  res = bb.event.register(self.dm_event_handler_name,
                                          lambda x: self.dm.check(self) if self.state in [runQueueRunning, runQueueCleanUp] else False,
-                                         ('bb.event.HeartbeatEvent',))
+                                         ('bb.event.HeartbeatEvent',), data=self.cfgData)
                  self.dm_event_handler_registered = True
 
             dump = self.cooker.configuration.dump_signatures
@@ -1498,7 +1519,7 @@ class RunQueue:
         build_done = self.state is runQueueComplete or self.state is runQueueFailed
 
         if build_done and self.dm_event_handler_registered:
-            bb.event.remove(self.dm_event_handler_name, None)
+            bb.event.remove(self.dm_event_handler_name, None, data=self.cfgData)
             self.dm_event_handler_registered = False
 
         if build_done and self.rqexe:
@@ -1557,7 +1578,8 @@ class RunQueue:
 
     def rq_dump_sigfn(self, fn, options):
         bb_cache = bb.cache.NoCache(self.cooker.databuilder)
-        the_data = bb_cache.loadDataFull(fn, self.cooker.collection.get_file_appends(fn))
+        mc = bb.runqueue.mc_from_tid(fn)
+        the_data = bb_cache.loadDataFull(fn, self.cooker.collections[mc].get_file_appends(fn))
         siggen = bb.parse.siggen
         dataCaches = self.rqdata.dataCaches
         siggen.dump_sigfn(fn, dataCaches, options)
@@ -1724,8 +1746,7 @@ class RunQueueExecute:
         self.holdoff_need_update = True
         self.sqdone = False
 
-        self.stats = RunQueueStats(len(self.rqdata.runtaskentries))
-        self.sq_stats = RunQueueStats(len(self.rqdata.runq_setscene_tids))
+        self.stats = RunQueueStats(len(self.rqdata.runtaskentries), len(self.rqdata.runq_setscene_tids))
 
         for mc in rq.worker:
             rq.worker[mc].pipe.setrunqueueexec(self)
@@ -1753,7 +1774,7 @@ class RunQueueExecute:
         for scheduler in schedulers:
             if self.scheduler == scheduler.name:
                 self.sched = scheduler(self, self.rqdata)
-                logger.debug(1, "Using runqueue scheduler '%s'", scheduler.name)
+                logger.debug("Using runqueue scheduler '%s'", scheduler.name)
                 break
         else:
             bb.fatal("Invalid scheduler '%s'.  Available schedulers: %s" %
@@ -1763,7 +1784,7 @@ class RunQueueExecute:
         self.sqdata = SQData()
         build_scenequeue_data(self.sqdata, self.rqdata, self.rq, self.cooker, self.stampcache, self)
 
-    def runqueue_process_waitpid(self, task, status):
+    def runqueue_process_waitpid(self, task, status, fakerootlog=None):
 
         # self.build_stamps[pid] may not exist when use shared work directory.
         if task in self.build_stamps:
@@ -1776,9 +1797,10 @@ class RunQueueExecute:
             else:
                 self.sq_task_complete(task)
             self.sq_live.remove(task)
+            self.stats.updateActiveSetscene(len(self.sq_live))
         else:
             if status != 0:
-                self.task_fail(task, status)
+                self.task_fail(task, status, fakerootlog=fakerootlog)
             else:
                 self.task_complete(task)
         return True
@@ -1809,7 +1831,7 @@ class RunQueueExecute:
     def finish(self):
         self.rq.state = runQueueCleanUp
 
-        active = self.stats.active + self.sq_stats.active
+        active = self.stats.active + len(self.sq_live)
         if active > 0:
             bb.event.fire(runQueueExitWait(active), self.cfgData)
             self.rq.read_workers()
@@ -1842,7 +1864,7 @@ class RunQueueExecute:
         return valid
 
     def can_start_task(self):
-        active = self.stats.active + self.sq_stats.active
+        active = self.stats.active + len(self.sq_live)
         can_start = active < self.number_tasks
         return can_start
 
@@ -1891,7 +1913,13 @@ class RunQueueExecute:
                     break
             if alldeps:
                 self.setbuildable(revdep)
-                logger.debug(1, "Marking task %s as buildable", revdep)
+                logger.debug("Marking task %s as buildable", revdep)
+
+        for t in self.sq_deferred.copy():
+            if self.sq_deferred[t] == task:
+                logger.debug2("Deferred task %s now buildable" % t)
+                del self.sq_deferred[t]
+                update_scenequeue_data([t], self.sqdata, self.rqdata, self.rq, self.cooker, self.stampcache, self, summary=False)
 
     def task_complete(self, task):
         self.stats.taskCompleted()
@@ -1899,14 +1927,31 @@ class RunQueueExecute:
         self.task_completeoutright(task)
         self.runq_tasksrun.add(task)
 
-    def task_fail(self, task, exitcode):
+    def task_fail(self, task, exitcode, fakerootlog=None):
         """
         Called when a task has failed
         Updates the state engine with the failure
         """
         self.stats.taskFailed()
         self.failed_tids.append(task)
-        bb.event.fire(runQueueTaskFailed(task, self.stats, exitcode, self.rq), self.cfgData)
+
+        fakeroot_log = ""
+        if fakerootlog and os.path.exists(fakerootlog):
+            with open(fakerootlog) as fakeroot_log_file:
+                fakeroot_failed = False
+                for line in reversed(fakeroot_log_file.readlines()):
+                    for fakeroot_error in ['mismatch', 'error', 'fatal']:
+                        if fakeroot_error in line.lower():
+                            fakeroot_failed = True
+                    if 'doing new pid setup and server start' in line:
+                        break
+                    fakeroot_log = line + fakeroot_log
+
+            if not fakeroot_failed:
+                fakeroot_log = None
+
+        bb.event.fire(runQueueTaskFailed(task, self.stats, exitcode, self.rq, fakeroot_log=fakeroot_log), self.cfgData)
+
         if self.rqdata.taskData[''].abort:
             self.rq.state = runQueueCleanUp
 
@@ -1921,8 +1966,8 @@ class RunQueueExecute:
     def summarise_scenequeue_errors(self):
         err = False
         if not self.sqdone:
-            logger.debug(1, 'We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered)))
-            completeevent = sceneQueueComplete(self.sq_stats, self.rq)
+            logger.debug('We could skip tasks %s', "\n".join(sorted(self.scenequeue_covered)))
+            completeevent = sceneQueueComplete(self.stats, self.rq)
             bb.event.fire(completeevent, self.cfgData)
         if self.sq_deferred:
             logger.error("Scenequeue had deferred entries: %s" % pprint.pformat(self.sq_deferred))
@@ -1934,6 +1979,10 @@ class RunQueueExecute:
             logger.error("Scenequeue had holdoff tasks: %s" % pprint.pformat(self.holdoff_tasks))
             err = True
 
+        for tid in self.scenequeue_covered.intersection(self.scenequeue_notcovered):
+            # No task should end up in both covered and uncovered, that is a bug.
+            logger.error("Setscene task %s in both covered and notcovered." % tid)
+
         for tid in self.rqdata.runq_setscene_tids:
             if tid not in self.scenequeue_covered and tid not in self.scenequeue_notcovered:
                 err = True
@@ -1978,7 +2027,7 @@ class RunQueueExecute:
                 if nexttask in self.sq_buildable and nexttask not in self.sq_running and self.sqdata.stamps[nexttask] not in self.build_stamps.values():
                     if nexttask not in self.sqdata.unskippable and len(self.sqdata.sq_revdeps[nexttask]) > 0 and self.sqdata.sq_revdeps[nexttask].issubset(self.scenequeue_covered) and self.check_dependencies(nexttask, self.sqdata.sq_revdeps[nexttask]):
                         if nexttask not in self.rqdata.target_tids:
-                            logger.debug(2, "Skipping setscene for task %s" % nexttask)
+                            logger.debug2("Skipping setscene for task %s" % nexttask)
                             self.sq_task_skip(nexttask)
                             self.scenequeue_notneeded.add(nexttask)
                             if nexttask in self.sq_deferred:
@@ -1991,28 +2040,26 @@ class RunQueueExecute:
                     if nexttask in self.sq_deferred:
                         if self.sq_deferred[nexttask] not in self.runq_complete:
                             continue
-                        logger.debug(1, "Task %s no longer deferred" % nexttask)
+                        logger.debug("Task %s no longer deferred" % nexttask)
                         del self.sq_deferred[nexttask]
                         valid = self.rq.validate_hashes(set([nexttask]), self.cooker.data, 0, False, summary=False)
                         if not valid:
-                            logger.debug(1, "%s didn't become valid, skipping setscene" % nexttask)
+                            logger.debug("%s didn't become valid, skipping setscene" % nexttask)
                             self.sq_task_failoutright(nexttask)
                             return True
-                        else:
-                            self.sqdata.outrightfail.remove(nexttask)
                     if nexttask in self.sqdata.outrightfail:
-                        logger.debug(2, 'No package found, so skipping setscene task %s', nexttask)
+                        logger.debug2('No package found, so skipping setscene task %s', nexttask)
                         self.sq_task_failoutright(nexttask)
                         return True
                     if nexttask in self.sqdata.unskippable:
-                        logger.debug(2, "Setscene task %s is unskippable" % nexttask)
+                        logger.debug2("Setscene task %s is unskippable" % nexttask)
                     task = nexttask
                     break
         if task is not None:
             (mc, fn, taskname, taskfn) = split_tid_mcfn(task)
             taskname = taskname + "_setscene"
             if self.rq.check_stamp_task(task, taskname_from_tid(task), recurse = True, cache=self.stampcache):
-                logger.debug(2, 'Stamp for underlying task %s is current, so skipping setscene variant', task)
+                logger.debug2('Stamp for underlying task %s is current, so skipping setscene variant', task)
                 self.sq_task_failoutright(task)
                 return True
 
@@ -2022,16 +2069,16 @@ class RunQueueExecute:
                     return True
 
             if self.rq.check_stamp_task(task, taskname, cache=self.stampcache):
-                logger.debug(2, 'Setscene stamp current task %s, so skip it and its dependencies', task)
+                logger.debug2('Setscene stamp current task %s, so skip it and its dependencies', task)
                 self.sq_task_skip(task)
                 return True
 
             if self.cooker.configuration.skipsetscene:
-                logger.debug(2, 'No setscene tasks should be executed. Skipping %s', task)
+                logger.debug2('No setscene tasks should be executed. Skipping %s', task)
                 self.sq_task_failoutright(task)
                 return True
 
-            startevent = sceneQueueTaskStarted(task, self.sq_stats, self.rq)
+            startevent = sceneQueueTaskStarted(task, self.stats, self.rq)
             bb.event.fire(startevent, self.cfgData)
 
             taskdepdata = self.sq_build_taskdepdata(task)
@@ -2042,17 +2089,17 @@ class RunQueueExecute:
             if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not self.cooker.configuration.dry_run:
                 if not mc in self.rq.fakeworker:
                     self.rq.start_fakeworker(self, mc)
-                self.rq.fakeworker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, True, self.cooker.collection.get_file_appends(taskfn), taskdepdata, False)) + b"</runtask>")
+                self.rq.fakeworker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, True, self.cooker.collections[mc].get_file_appends(taskfn), taskdepdata, False)) + b"</runtask>")
                 self.rq.fakeworker[mc].process.stdin.flush()
             else:
-                self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, True, self.cooker.collection.get_file_appends(taskfn), taskdepdata, False)) + b"</runtask>")
+                self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, True, self.cooker.collections[mc].get_file_appends(taskfn), taskdepdata, False)) + b"</runtask>")
                 self.rq.worker[mc].process.stdin.flush()
 
             self.build_stamps[task] = bb.build.stampfile(taskname, self.rqdata.dataCaches[mc], taskfn, noextra=True)
             self.build_stamps2.append(self.build_stamps[task])
             self.sq_running.add(task)
             self.sq_live.add(task)
-            self.sq_stats.taskActive()
+            self.stats.updateActiveSetscene(len(self.sq_live))
             if self.can_start_task():
                 return True
 
@@ -2089,12 +2136,12 @@ class RunQueueExecute:
                     return True
 
             if task in self.tasks_covered:
-                logger.debug(2, "Setscene covered task %s", task)
+                logger.debug2("Setscene covered task %s", task)
                 self.task_skip(task, "covered")
                 return True
 
             if self.rq.check_stamp_task(task, taskname, cache=self.stampcache):
-                logger.debug(2, "Stamp current task %s", task)
+                logger.debug2("Stamp current task %s", task)
 
                 self.task_skip(task, "existing")
                 self.runq_tasksrun.add(task)
@@ -2129,10 +2176,10 @@ class RunQueueExecute:
                         self.rq.state = runQueueFailed
                         self.stats.taskFailed()
                         return True
-                self.rq.fakeworker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, False, self.cooker.collection.get_file_appends(taskfn), taskdepdata, self.rqdata.setscene_enforce)) + b"</runtask>")
+                self.rq.fakeworker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, False, self.cooker.collections[mc].get_file_appends(taskfn), taskdepdata, self.rqdata.setscene_enforce)) + b"</runtask>")
                 self.rq.fakeworker[mc].process.stdin.flush()
             else:
-                self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, False, self.cooker.collection.get_file_appends(taskfn), taskdepdata, self.rqdata.setscene_enforce)) + b"</runtask>")
+                self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, taskhash, unihash, False, self.cooker.collections[mc].get_file_appends(taskfn), taskdepdata, self.rqdata.setscene_enforce)) + b"</runtask>")
                 self.rq.worker[mc].process.stdin.flush()
 
             self.build_stamps[task] = bb.build.stampfile(taskname, self.rqdata.dataCaches[mc], taskfn, noextra=True)
@@ -2142,7 +2189,7 @@ class RunQueueExecute:
             if self.can_start_task():
                 return True
 
-        if self.stats.active > 0 or self.sq_stats.active > 0:
+        if self.stats.active > 0 or len(self.sq_live) > 0:
             self.rq.read_workers()
             return self.rq.active_fds()
 
@@ -2150,7 +2197,8 @@ class RunQueueExecute:
         if self.sq_deferred:
             tid = self.sq_deferred.pop(list(self.sq_deferred.keys())[0])
             logger.warning("Runqeueue deadlocked on deferred tasks, forcing task %s" % tid)
-            self.sq_task_failoutright(tid)
+            if tid not in self.runq_complete:
+                self.sq_task_failoutright(tid)
             return True
 
         if len(self.failed_tids) != 0:
@@ -2264,10 +2312,16 @@ class RunQueueExecute:
             self.updated_taskhash_queue.remove((tid, unihash))
 
             if unihash != self.rqdata.runtaskentries[tid].unihash:
-                hashequiv_logger.verbose("Task %s unihash changed to %s" % (tid, unihash))
-                self.rqdata.runtaskentries[tid].unihash = unihash
-                bb.parse.siggen.set_unihash(tid, unihash)
-                toprocess.add(tid)
+                # Make sure we rehash any other tasks with the same task hash that we're deferred against.
+                torehash = [tid]
+                for deftid in self.sq_deferred:
+                    if self.sq_deferred[deftid] == tid:
+                        torehash.append(deftid)
+                for hashtid in torehash:
+                    hashequiv_logger.verbose("Task %s unihash changed to %s" % (hashtid, unihash))
+                    self.rqdata.runtaskentries[hashtid].unihash = unihash
+                    bb.parse.siggen.set_unihash(hashtid, unihash)
+                    toprocess.add(hashtid)
 
         # Work out all tasks which depend upon these
         total = set()
@@ -2298,7 +2352,8 @@ class RunQueueExecute:
                 if len(self.rqdata.runtaskentries[p].depends) and not self.rqdata.runtaskentries[tid].depends.isdisjoint(total):
                     continue
                 orighash = self.rqdata.runtaskentries[tid].hash
-                newhash = bb.parse.siggen.get_taskhash(tid, self.rqdata.runtaskentries[tid].depends, self.rqdata.dataCaches[mc_from_tid(tid)])
+                dc = bb.parse.siggen.get_data_caches(self.rqdata.dataCaches, mc_from_tid(tid))
+                newhash = bb.parse.siggen.get_taskhash(tid, self.rqdata.runtaskentries[tid].depends, dc)
                 origuni = self.rqdata.runtaskentries[tid].unihash
                 newuni = bb.parse.siggen.get_unihash(tid)
                 # FIXME, need to check it can come from sstate at all for determinism?
@@ -2313,7 +2368,7 @@ class RunQueueExecute:
                     remapped = True
 
                 if not remapped:
-                    #logger.debug(1, "Task %s hash changes: %s->%s %s->%s" % (tid, orighash, newhash, origuni, newuni))
+                    #logger.debug("Task %s hash changes: %s->%s %s->%s" % (tid, orighash, newhash, origuni, newuni))
                     self.rqdata.runtaskentries[tid].hash = newhash
                     self.rqdata.runtaskentries[tid].unihash = newuni
                     changed.add(tid)
@@ -2328,7 +2383,7 @@ class RunQueueExecute:
             for mc in self.rq.fakeworker:
                 self.rq.fakeworker[mc].process.stdin.write(b"<newtaskhashes>" + pickle.dumps(bb.parse.siggen.get_taskhashes()) + b"</newtaskhashes>")
 
-            hashequiv_logger.debug(1, pprint.pformat("Tasks changed:\n%s" % (changed)))
+            hashequiv_logger.debug(pprint.pformat("Tasks changed:\n%s" % (changed)))
 
         for tid in changed:
             if tid not in self.rqdata.runq_setscene_tids:
@@ -2347,7 +2402,7 @@ class RunQueueExecute:
             # Check no tasks this covers are running
             for dep in self.sqdata.sq_covered_tasks[tid]:
                 if dep in self.runq_running and dep not in self.runq_complete:
-                    hashequiv_logger.debug(2, "Task %s is running which blocks setscene for %s from running" % (dep, tid))
+                    hashequiv_logger.debug2("Task %s is running which blocks setscene for %s from running" % (dep, tid))
                     valid = False
                     break
             if not valid:
@@ -2406,6 +2461,11 @@ class RunQueueExecute:
 
         if update_tasks:
             self.sqdone = False
+            for tid in [t[0] for t in update_tasks]:
+                h = pending_hash_index(tid, self.rqdata)
+                if h in self.sqdata.hashes and tid != self.sqdata.hashes[h]:
+                    self.sq_deferred[tid] = self.sqdata.hashes[h]
+                    bb.note("Deferring %s after %s" % (tid, self.sqdata.hashes[h]))
             update_scenequeue_data([t[0] for t in update_tasks], self.sqdata, self.rqdata, self.rq, self.cooker, self.stampcache, self, summary=False)
 
         for (tid, harddepfail, origvalid) in update_tasks:
@@ -2415,13 +2475,20 @@ class RunQueueExecute:
                 self.sq_task_failoutright(tid)
 
         if changed:
+            self.stats.updateCovered(len(self.scenequeue_covered), len(self.scenequeue_notcovered))
             self.holdoff_need_update = True
 
     def scenequeue_updatecounters(self, task, fail=False):
 
         for dep in sorted(self.sqdata.sq_deps[task]):
             if fail and task in self.sqdata.sq_harddeps and dep in self.sqdata.sq_harddeps[task]:
-                logger.debug(2, "%s was unavailable and is a hard dependency of %s so skipping" % (task, dep))
+                if dep in self.scenequeue_covered or dep in self.scenequeue_notcovered:
+                    # dependency could be already processed, e.g. noexec setscene task
+                    continue
+                noexec, stamppresent = check_setscene_stamps(dep, self.rqdata, self.rq, self.stampcache)
+                if noexec or stamppresent:
+                    continue
+                logger.debug2("%s was unavailable and is a hard dependency of %s so skipping" % (task, dep))
                 self.sq_task_failoutright(dep)
                 continue
             if self.sqdata.sq_revdeps[dep].issubset(self.scenequeue_covered | self.scenequeue_notcovered):
@@ -2442,6 +2509,7 @@ class RunQueueExecute:
                         new.add(dep)
             next = new
 
+        self.stats.updateCovered(len(self.scenequeue_covered), len(self.scenequeue_notcovered))
         self.holdoff_need_update = True
 
     def sq_task_completeoutright(self, task):
@@ -2451,7 +2519,7 @@ class RunQueueExecute:
         completed dependencies as buildable
         """
 
-        logger.debug(1, 'Found task %s which could be accelerated', task)
+        logger.debug('Found task %s which could be accelerated', task)
         self.scenequeue_covered.add(task)
         self.scenequeue_updatecounters(task)
 
@@ -2465,13 +2533,11 @@ class RunQueueExecute:
                 self.rq.state = runQueueCleanUp
 
     def sq_task_complete(self, task):
-        self.sq_stats.taskCompleted()
-        bb.event.fire(sceneQueueTaskCompleted(task, self.sq_stats, self.rq), self.cfgData)
+        bb.event.fire(sceneQueueTaskCompleted(task, self.stats, self.rq), self.cfgData)
         self.sq_task_completeoutright(task)
 
     def sq_task_fail(self, task, result):
-        self.sq_stats.taskFailed()
-        bb.event.fire(sceneQueueTaskFailed(task, self.sq_stats, result, self), self.cfgData)
+        bb.event.fire(sceneQueueTaskFailed(task, self.stats, result, self), self.cfgData)
         self.scenequeue_notcovered.add(task)
         self.scenequeue_updatecounters(task, True)
         self.sq_check_taskfail(task)
@@ -2479,8 +2545,6 @@ class RunQueueExecute:
     def sq_task_failoutright(self, task):
         self.sq_running.add(task)
         self.sq_buildable.add(task)
-        self.sq_stats.taskSkipped()
-        self.sq_stats.taskCompleted()
         self.scenequeue_notcovered.add(task)
         self.scenequeue_updatecounters(task, True)
 
@@ -2488,8 +2552,6 @@ class RunQueueExecute:
         self.sq_running.add(task)
         self.sq_buildable.add(task)
         self.sq_task_completeoutright(task)
-        self.sq_stats.taskSkipped()
-        self.sq_stats.taskCompleted()
 
     def sq_build_taskdepdata(self, task):
         def getsetscenedeps(tid):
@@ -2743,8 +2805,55 @@ def build_scenequeue_data(sqdata, rqdata, rq, cooker, stampcache, sqrq):
     sqdata.stamppresent = set()
     sqdata.valid = set()
 
+    sqdata.hashes = {}
+    sqrq.sq_deferred = {}
+    for mc in sorted(sqdata.multiconfigs):
+        for tid in sorted(sqdata.sq_revdeps):
+            if mc_from_tid(tid) != mc:
+                continue
+            h = pending_hash_index(tid, rqdata)
+            if h not in sqdata.hashes:
+                sqdata.hashes[h] = tid
+            else:
+                sqrq.sq_deferred[tid] = sqdata.hashes[h]
+                bb.note("Deferring %s after %s" % (tid, sqdata.hashes[h]))
+
     update_scenequeue_data(sqdata.sq_revdeps, sqdata, rqdata, rq, cooker, stampcache, sqrq, summary=True)
 
+    # Compute a list of 'stale' sstate tasks where the current hash does not match the one
+    # in any stamp files. Pass the list out to metadata as an event.
+    found = {}
+    for tid in rqdata.runq_setscene_tids:
+        (mc, fn, taskname, taskfn) = split_tid_mcfn(tid)
+        stamps = bb.build.find_stale_stamps(taskname, rqdata.dataCaches[mc], taskfn)
+        if stamps:
+            if mc not in found:
+                found[mc] = {}
+            found[mc][tid] = stamps
+    for mc in found:
+        event = bb.event.StaleSetSceneTasks(found[mc])
+        bb.event.fire(event, cooker.databuilder.mcdata[mc])
+
+def check_setscene_stamps(tid, rqdata, rq, stampcache, noexecstamp=False):
+
+    (mc, fn, taskname, taskfn) = split_tid_mcfn(tid)
+
+    taskdep = rqdata.dataCaches[mc].task_deps[taskfn]
+
+    if 'noexec' in taskdep and taskname in taskdep['noexec']:
+        bb.build.make_stamp(taskname + "_setscene", rqdata.dataCaches[mc], taskfn)
+        return True, False
+
+    if rq.check_stamp_task(tid, taskname + "_setscene", cache=stampcache):
+        logger.debug2('Setscene stamp current for task %s', tid)
+        return False, True
+
+    if rq.check_stamp_task(tid, taskname, recurse = True, cache=stampcache):
+        logger.debug2('Normal stamp current for task %s', tid)
+        return False, True
+
+    return False, False
+
 def update_scenequeue_data(tids, sqdata, rqdata, rq, cooker, stampcache, sqrq, summary=True):
 
     tocheck = set()
@@ -2754,25 +2863,17 @@ def update_scenequeue_data(tids, sqdata, rqdata, rq, cooker, stampcache, sqrq, s
             sqdata.stamppresent.remove(tid)
         if tid in sqdata.valid:
             sqdata.valid.remove(tid)
+        if tid in sqdata.outrightfail:
+            sqdata.outrightfail.remove(tid)
 
-        (mc, fn, taskname, taskfn) = split_tid_mcfn(tid)
-
-        taskdep = rqdata.dataCaches[mc].task_deps[taskfn]
+        noexec, stamppresent = check_setscene_stamps(tid, rqdata, rq, stampcache, noexecstamp=True)
 
-        if 'noexec' in taskdep and taskname in taskdep['noexec']:
+        if noexec:
             sqdata.noexec.add(tid)
             sqrq.sq_task_skip(tid)
-            bb.build.make_stamp(taskname + "_setscene", rqdata.dataCaches[mc], taskfn)
             continue
 
-        if rq.check_stamp_task(tid, taskname + "_setscene", cache=stampcache):
-            logger.debug(2, 'Setscene stamp current for task %s', tid)
-            sqdata.stamppresent.add(tid)
-            sqrq.sq_task_skip(tid)
-            continue
-
-        if rq.check_stamp_task(tid, taskname, recurse = True, cache=stampcache):
-            logger.debug(2, 'Normal stamp current for task %s', tid)
+        if stamppresent:
             sqdata.stamppresent.add(tid)
             sqrq.sq_task_skip(tid)
             continue
@@ -2781,28 +2882,20 @@ def update_scenequeue_data(tids, sqdata, rqdata, rq, cooker, stampcache, sqrq, s
 
     sqdata.valid |= rq.validate_hashes(tocheck, cooker.data, len(sqdata.stamppresent), False, summary=summary)
 
-    sqdata.hashes = {}
-    for mc in sorted(sqdata.multiconfigs):
-        for tid in sorted(sqdata.sq_revdeps):
-            if mc_from_tid(tid) != mc:
-                continue
-            if tid in sqdata.stamppresent:
-                continue
-            if tid in sqdata.valid:
-                continue
-            if tid in sqdata.noexec:
-                continue
-            if tid in sqrq.scenequeue_notcovered:
-                continue
-            sqdata.outrightfail.add(tid)
-
-            h = pending_hash_index(tid, rqdata)
-            if h not in sqdata.hashes:
-                sqdata.hashes[h] = tid
-            else:
-                sqrq.sq_deferred[tid] = sqdata.hashes[h]
-                bb.note("Deferring %s after %s" % (tid, sqdata.hashes[h]))
-
+    for tid in tids:
+        if tid in sqdata.stamppresent:
+            continue
+        if tid in sqdata.valid:
+            continue
+        if tid in sqdata.noexec:
+            continue
+        if tid in sqrq.scenequeue_covered:
+            continue
+        if tid in sqrq.scenequeue_notcovered:
+            continue
+        if tid in sqrq.sq_deferred:
+            continue
+        sqdata.outrightfail.add(tid)
 
 class TaskFailure(Exception):
     """
@@ -2866,12 +2959,16 @@ class runQueueTaskFailed(runQueueEvent):
     """
     Event notifying a task failed
     """
-    def __init__(self, task, stats, exitcode, rq):
+    def __init__(self, task, stats, exitcode, rq, fakeroot_log=None):
         runQueueEvent.__init__(self, task, stats, rq)
         self.exitcode = exitcode
+        self.fakeroot_log = fakeroot_log
 
     def __str__(self):
-        return "Task (%s) failed with exit code '%s'" % (self.taskstring, self.exitcode)
+        if self.fakeroot_log:
+            return "Task (%s) failed with exit code '%s' \nPseudo log:\n%s" % (self.taskstring, self.exitcode, self.fakeroot_log)
+        else:
+            return "Task (%s) failed with exit code '%s'" % (self.taskstring, self.exitcode)
 
 class sceneQueueTaskFailed(sceneQueueEvent):
     """
@@ -2923,7 +3020,7 @@ class runQueuePipe():
     """
     Abstraction for a pipe between a worker thread and the server
     """
-    def __init__(self, pipein, pipeout, d, rq, rqexec):
+    def __init__(self, pipein, pipeout, d, rq, rqexec, fakerootlogs=None):
         self.input = pipein
         if pipeout:
             pipeout.close()
@@ -2932,6 +3029,7 @@ class runQueuePipe():
         self.d = d
         self.rq = rq
         self.rqexec = rqexec
+        self.fakerootlogs = fakerootlogs
 
     def setrunqueueexec(self, rqexec):
         self.rqexec = rqexec
@@ -2977,7 +3075,11 @@ class runQueuePipe():
                     task, status = pickle.loads(self.queue[10:index])
                 except (ValueError, pickle.UnpicklingError, AttributeError, IndexError) as e:
                     bb.msg.fatal("RunQueue", "failed load pickle '%s': '%s'" % (e, self.queue[10:index]))
-                self.rqexec.runqueue_process_waitpid(task, status)
+                (_, _, _, taskfn) = split_tid_mcfn(task)
+                fakerootlog = None
+                if self.fakerootlogs and taskfn and taskfn in self.fakerootlogs:
+                    fakerootlog = self.fakerootlogs[taskfn]
+                self.rqexec.runqueue_process_waitpid(task, status, fakerootlog=fakerootlog)
                 found = True
                 self.queue = self.queue[index+11:]
                 index = self.queue.find(b"</exitcode>")
@@ -2990,16 +3092,15 @@ class runQueuePipe():
             print("Warning, worker left partial message: %s" % self.queue)
         self.input.close()
 
-def get_setscene_enforce_whitelist(d):
+def get_setscene_enforce_whitelist(d, targets):
     if d.getVar('BB_SETSCENE_ENFORCE') != '1':
         return None
     whitelist = (d.getVar("BB_SETSCENE_ENFORCE_WHITELIST") or "").split()
     outlist = []
     for item in whitelist[:]:
         if item.startswith('%:'):
-            for target in sys.argv[1:]:
-                if not target.startswith('-'):
-                    outlist.append(target.split(':')[0] + ':' + item.split(':')[1])
+            for (mc, target, task, fn) in targets:
+                outlist.append(target + ':' + item.split(':')[1])
         else:
             outlist.append(item)
     return outlist
diff --git a/bitbake/lib/bb/server/process.py b/bitbake/lib/bb/server/process.py
index 9ec79f5b..07bb785a 100644
--- a/bitbake/lib/bb/server/process.py
+++ b/bitbake/lib/bb/server/process.py
@@ -25,6 +25,7 @@ import subprocess
 import errno
 import re
 import datetime
+import pickle
 import bb.server.xmlrpcserver
 from bb import daemonize
 from multiprocessing import queues
@@ -34,12 +35,15 @@ logger = logging.getLogger('BitBake')
 class ProcessTimeout(SystemExit):
     pass
 
-class ProcessServer(multiprocessing.Process):
+def serverlog(msg):
+    print(str(os.getpid()) + " " +  datetime.datetime.now().strftime('%H:%M:%S.%f') + " " + msg)
+    sys.stdout.flush()
+
+class ProcessServer():
     profile_filename = "profile.log"
     profile_processed_filename = "profile.log.processed"
 
-    def __init__(self, lock, sock, sockname):
-        multiprocessing.Process.__init__(self)
+    def __init__(self, lock, lockname, sock, sockname, server_timeout, xmlrpcinterface):
         self.command_channel = False
         self.command_channel_reply = False
         self.quit = False
@@ -47,6 +51,7 @@ class ProcessServer(multiprocessing.Process):
         self.next_heartbeat = time.time()
 
         self.event_handle = None
+        self.hadanyui = False
         self.haveui = False
         self.maxuiwait = 30
         self.xmlrpc = False
@@ -54,9 +59,14 @@ class ProcessServer(multiprocessing.Process):
         self._idlefuns = {}
 
         self.bitbake_lock = lock
+        self.bitbake_lock_name = lockname
         self.sock = sock
         self.sockname = sockname
 
+        self.server_timeout = server_timeout
+        self.timeout = self.server_timeout
+        self.xmlrpcinterface = xmlrpcinterface
+
     def register_idle_function(self, function, data):
         """Register a function to be called while the server is idle"""
         assert hasattr(function, '__call__')
@@ -67,22 +77,7 @@ class ProcessServer(multiprocessing.Process):
         if self.xmlrpcinterface[0]:
             self.xmlrpc = bb.server.xmlrpcserver.BitBakeXMLRPCServer(self.xmlrpcinterface, self.cooker, self)
 
-            print("Bitbake XMLRPC server address: %s, server port: %s" % (self.xmlrpc.host, self.xmlrpc.port))
-
-        heartbeat_event = self.cooker.data.getVar('BB_HEARTBEAT_EVENT')
-        if heartbeat_event:
-            try:
-                self.heartbeat_seconds = float(heartbeat_event)
-            except:
-                bb.warn('Ignoring invalid BB_HEARTBEAT_EVENT=%s, must be a float specifying seconds.' % heartbeat_event)
-
-        self.timeout = self.server_timeout or self.cooker.data.getVar('BB_SERVER_TIMEOUT')
-        try:
-            if self.timeout:
-                self.timeout = float(self.timeout)
-        except:
-            bb.warn('Ignoring invalid BB_SERVER_TIMEOUT=%s, must be a float specifying seconds.' % self.timeout)
-
+            serverlog("Bitbake XMLRPC server address: %s, server port: %s" % (self.xmlrpc.host, self.xmlrpc.port))
 
         try:
             self.bitbake_lock.seek(0)
@@ -93,7 +88,7 @@ class ProcessServer(multiprocessing.Process):
                 self.bitbake_lock.write("%s\n" % (os.getpid()))
             self.bitbake_lock.flush()
         except Exception as e:
-            print("Error writing to lock file: %s" % str(e))
+            serverlog("Error writing to lock file: %s" % str(e))
             pass
 
         if self.cooker.configuration.profile:
@@ -107,7 +102,7 @@ class ProcessServer(multiprocessing.Process):
 
             prof.dump_stats("profile.log")
             bb.utils.process_profilelog("profile.log")
-            print("Raw profiling information saved to profile.log and processed statistics to profile.log.processed")
+            serverlog("Raw profiling information saved to profile.log and processed statistics to profile.log.processed")
 
         else:
             ret = self.main()
@@ -126,10 +121,11 @@ class ProcessServer(multiprocessing.Process):
         fds = [self.sock]
         if self.xmlrpc:
             fds.append(self.xmlrpc)
-        print("Entering server connection loop")
+        seendata = False
+        serverlog("Entering server connection loop")
 
         def disconnect_client(self, fds):
-            print("Disconnecting Client")
+            serverlog("Disconnecting Client")
             if self.controllersock:
                 fds.remove(self.controllersock)
                 self.controllersock.close()
@@ -147,12 +143,12 @@ class ProcessServer(multiprocessing.Process):
                 self.haveui = False
             ready = select.select(fds,[],[],0)[0]
             if newconnections:
-                print("Starting new client")
+                serverlog("Starting new client")
                 conn = newconnections.pop(-1)
                 fds.append(conn)
                 self.controllersock = conn
-            elif self.timeout is None and not ready:
-                print("No timeout, exiting.")
+            elif not self.timeout and not ready:
+                serverlog("No timeout, exiting.")
                 self.quit = True
 
         self.lastui = time.time()
@@ -161,17 +157,17 @@ class ProcessServer(multiprocessing.Process):
                 while select.select([self.sock],[],[],0)[0]:
                     controllersock, address = self.sock.accept()
                     if self.controllersock:
-                        print("Queuing %s (%s)" % (str(ready), str(newconnections)))
+                        serverlog("Queuing %s (%s)" % (str(ready), str(newconnections)))
                         newconnections.append(controllersock)
                     else:
-                        print("Accepting %s (%s)" % (str(ready), str(newconnections)))
+                        serverlog("Accepting %s (%s)" % (str(ready), str(newconnections)))
                         self.controllersock = controllersock
                         fds.append(controllersock)
             if self.controllersock in ready:
                 try:
-                    print("Processing Client")
+                    serverlog("Processing Client")
                     ui_fds = recvfds(self.controllersock, 3)
-                    print("Connecting Client")
+                    serverlog("Connecting Client")
 
                     # Where to write events to
                     writer = ConnectionWriter(ui_fds[0])
@@ -188,20 +184,21 @@ class ProcessServer(multiprocessing.Process):
                     self.command_channel_reply = writer
 
                     self.haveui = True
+                    self.hadanyui = True
 
                 except (EOFError, OSError):
                     disconnect_client(self, fds)
 
             if not self.timeout == -1.0 and not self.haveui and self.timeout and \
                     (self.lastui + self.timeout) < time.time():
-                print("Server timeout, exiting.")
+                serverlog("Server timeout, exiting.")
                 self.quit = True
 
             # If we don't see a UI connection within maxuiwait, its unlikely we're going to see
             # one. We have had issue with processes hanging indefinitely so timing out UI-less
             # servers is useful.
-            if not self.haveui and not self.timeout and (self.lastui + self.maxuiwait) < time.time():
-                print("No UI connection within max timeout, exiting to avoid infinite loop.")
+            if not self.hadanyui and not self.xmlrpc and not self.timeout and (self.lastui + self.maxuiwait) < time.time():
+                serverlog("No UI connection within max timeout, exiting to avoid infinite loop.")
                 self.quit = True
 
             if self.command_channel in ready:
@@ -216,17 +213,38 @@ class ProcessServer(multiprocessing.Process):
                     self.quit = True
                     continue
                 try:
-                    print("Running command %s" % command)
+                    serverlog("Running command %s" % command)
                     self.command_channel_reply.send(self.cooker.command.runCommand(command))
+                    serverlog("Command Completed")
                 except Exception as e:
+                   serverlog('Exception in server main event loop running command %s (%s)' % (command, str(e)))
                    logger.exception('Exception in server main event loop running command %s (%s)' % (command, str(e)))
 
             if self.xmlrpc in ready:
                 self.xmlrpc.handle_requests()
 
+            if not seendata and hasattr(self.cooker, "data"):
+                heartbeat_event = self.cooker.data.getVar('BB_HEARTBEAT_EVENT')
+                if heartbeat_event:
+                    try:
+                        self.heartbeat_seconds = float(heartbeat_event)
+                    except:
+                        bb.warn('Ignoring invalid BB_HEARTBEAT_EVENT=%s, must be a float specifying seconds.' % heartbeat_event)
+
+                self.timeout = self.server_timeout or self.cooker.data.getVar('BB_SERVER_TIMEOUT')
+                try:
+                    if self.timeout:
+                        self.timeout = float(self.timeout)
+                except:
+                    bb.warn('Ignoring invalid BB_SERVER_TIMEOUT=%s, must be a float specifying seconds.' % self.timeout)
+                seendata = True
+
             ready = self.idle_commands(.1, fds)
 
-        print("Exiting")
+        if len(threading.enumerate()) != 1:
+            serverlog("More than one thread left?: " + str(threading.enumerate()))
+
+        serverlog("Exiting")
         # Remove the socket file so we don't get any more connections to avoid races
         try:
             os.unlink(self.sockname)
@@ -243,41 +261,73 @@ class ProcessServer(multiprocessing.Process):
 
         self.cooker.post_serve()
 
+        # Flush logs before we release the lock
+        sys.stdout.flush()
+        sys.stderr.flush()
+
         # Finally release the lockfile but warn about other processes holding it open
         lock = self.bitbake_lock
-        lockfile = lock.name
+        lockfile = self.bitbake_lock_name
+
+        def get_lock_contents(lockfile):
+            try:
+                with open(lockfile, "r") as f:
+                    return f.readlines()
+            except FileNotFoundError:
+                return None
+
+        lockcontents = get_lock_contents(lockfile)
+        serverlog("Original lockfile contents: " + str(lockcontents))
+
         lock.close()
         lock = None
 
         while not lock:
-            with bb.utils.timeout(3):
-                lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True)
-                if lock:
-                    # We hold the lock so we can remove the file (hide stale pid data)
-                    # via unlockfile.
-                    bb.utils.unlockfile(lock)
-                    return
-
+            i = 0
+            lock = None
+            while not lock and i < 30:
+                lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=False)
                 if not lock:
-                    # Some systems may not have lsof available
-                    procs = None
+                    newlockcontents = get_lock_contents(lockfile)
+                    if newlockcontents != lockcontents:
+                        # A new server was started, the lockfile contents changed, we can exit
+                        serverlog("Lockfile now contains different contents, exiting: " + str(newlockcontents))
+                        return
+                    time.sleep(0.1)
+                i += 1
+            if lock:
+                # We hold the lock so we can remove the file (hide stale pid data)
+                # via unlockfile.
+                bb.utils.unlockfile(lock)
+                serverlog("Exiting as we could obtain the lock")
+                return
+
+            if not lock:
+                # Some systems may not have lsof available
+                procs = None
+                try:
+                    procs = subprocess.check_output(["lsof", '-w', lockfile], stderr=subprocess.STDOUT)
+                except subprocess.CalledProcessError:
+                    # File was deleted?
+                    continue
+                except OSError as e:
+                    if e.errno != errno.ENOENT:
+                        raise
+                if procs is None:
+                    # Fall back to fuser if lsof is unavailable
                     try:
-                        procs = subprocess.check_output(["lsof", '-w', lockfile], stderr=subprocess.STDOUT)
+                        procs = subprocess.check_output(["fuser", '-v', lockfile], stderr=subprocess.STDOUT)
+                    except subprocess.CalledProcessError:
+                        # File was deleted?
+                        continue
                     except OSError as e:
                         if e.errno != errno.ENOENT:
                             raise
-                    if procs is None:
-                        # Fall back to fuser if lsof is unavailable
-                        try:
-                            procs = subprocess.check_output(["fuser", '-v', lockfile], stderr=subprocess.STDOUT)
-                        except OSError as e:
-                            if e.errno != errno.ENOENT:
-                                raise
-
-                    msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock"
-                    if procs:
-                        msg += ":\n%s" % str(procs)
-                    print(msg)
+
+                msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock"
+                if procs:
+                    msg += ":\n%s" % str(procs.decode("utf-8"))
+                serverlog(msg)
 
     def idle_commands(self, delay, fds=None):
         nextsleep = delay
@@ -315,8 +365,14 @@ class ProcessServer(multiprocessing.Process):
             self.next_heartbeat += self.heartbeat_seconds
             if self.next_heartbeat <= now:
                 self.next_heartbeat = now + self.heartbeat_seconds
-            heartbeat = bb.event.HeartbeatEvent(now)
-            bb.event.fire(heartbeat, self.cooker.data)
+            if hasattr(self.cooker, "data"):
+                heartbeat = bb.event.HeartbeatEvent(now)
+                try:
+                    bb.event.fire(heartbeat, self.cooker.data)
+                except Exception as exc:
+                    if not isinstance(exc, bb.BBHandledException):
+                        logger.exception('Running heartbeat function')
+                    self.quit = True
         if nextsleep and now + nextsleep > self.next_heartbeat:
             # Shorten timeout so that we we wake up in time for
             # the heartbeat.
@@ -345,7 +401,12 @@ class ServerCommunicator():
             logger.info("No reply from server in 30s")
             if not self.recv.poll(30):
                 raise ProcessTimeout("Timeout while waiting for a reply from the bitbake server (60s)")
-        return self.recv.get()
+        ret, exc = self.recv.get()
+        # Should probably turn all exceptions in exc back into exceptions?
+        # For now, at least handle BBHandledException
+        if exc and ("BBHandledException" in exc or "SystemExit" in exc):
+            raise bb.BBHandledException()
+        return ret, exc
 
     def updateFeatureSet(self, featureset):
         _, error = self.runCommand(["setFeatures", featureset])
@@ -378,39 +439,26 @@ class BitBakeProcessServerConnection(object):
         self.connection.recv.close()
         return
 
+start_log_format = '--- Starting bitbake server pid %s at %s ---'
+start_log_datetime_format = '%Y-%m-%d %H:%M:%S.%f'
+
 class BitBakeServer(object):
-    start_log_format = '--- Starting bitbake server pid %s at %s ---'
-    start_log_datetime_format = '%Y-%m-%d %H:%M:%S.%f'
 
-    def __init__(self, lock, sockname, configuration, featureset):
+    def __init__(self, lock, sockname, featureset, server_timeout, xmlrpcinterface):
 
-        self.configuration = configuration
+        self.server_timeout = server_timeout
+        self.xmlrpcinterface = xmlrpcinterface
         self.featureset = featureset
         self.sockname = sockname
         self.bitbake_lock = lock
         self.readypipe, self.readypipein = os.pipe()
 
-        # Create server control socket
-        if os.path.exists(sockname):
-            os.unlink(sockname)
-
         # Place the log in the builddirectory alongside the lock file
         logfile = os.path.join(os.path.dirname(self.bitbake_lock.name), "bitbake-cookerdaemon.log")
+        self.logfile = logfile
 
-        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        # AF_UNIX has path length issues so chdir here to workaround
-        cwd = os.getcwd()
-        try:
-            os.chdir(os.path.dirname(sockname))
-            self.sock.bind(os.path.basename(sockname))
-        finally:
-            os.chdir(cwd)
-        self.sock.listen(1)
-
-        os.set_inheritable(self.sock.fileno(), True)
         startdatetime = datetime.datetime.now()
         bb.daemonize.createDaemon(self._startServer, logfile)
-        self.sock.close()
         self.bitbake_lock.close()
         os.close(self.readypipein)
 
@@ -423,13 +471,13 @@ class BitBakeServer(object):
             try:
                 r = ready.get()
             except EOFError:
-                # Trap the child exitting/closing the pipe and error out
+                # Trap the child exiting/closing the pipe and error out
                 r = None
         if not r or r[0] != "r":
             ready.close()
             bb.error("Unable to start bitbake server (%s)" % str(r))
             if os.path.exists(logfile):
-                logstart_re = re.compile(self.start_log_format % ('([0-9]+)', '([0-9-]+ [0-9:.]+)'))
+                logstart_re = re.compile(start_log_format % ('([0-9]+)', '([0-9-]+ [0-9:.]+)'))
                 started = False
                 lines = []
                 lastlines = []
@@ -439,9 +487,9 @@ class BitBakeServer(object):
                             lines.append(line)
                         else:
                             lastlines.append(line)
-                            res = logstart_re.match(line.rstrip())
+                            res = logstart_re.search(line.rstrip())
                             if res:
-                                ldatetime = datetime.datetime.strptime(res.group(2), self.start_log_datetime_format)
+                                ldatetime = datetime.datetime.strptime(res.group(2), start_log_datetime_format)
                                 if ldatetime >= startdatetime:
                                     started = True
                                     lines.append(line)
@@ -462,26 +510,53 @@ class BitBakeServer(object):
         ready.close()
 
     def _startServer(self):
-        print(self.start_log_format % (os.getpid(), datetime.datetime.now().strftime(self.start_log_datetime_format)))
-        sys.stdout.flush()
-
-        server = ProcessServer(self.bitbake_lock, self.sock, self.sockname)
-        self.configuration.setServerRegIdleCallback(server.register_idle_function)
         os.close(self.readypipe)
-        writer = ConnectionWriter(self.readypipein)
+        os.set_inheritable(self.bitbake_lock.fileno(), True)
+        os.set_inheritable(self.readypipein, True)
+        serverscript = os.path.realpath(os.path.dirname(__file__) + "/../../../bin/bitbake-server")
+        os.execl(sys.executable, "bitbake-server", serverscript, "decafbad", str(self.bitbake_lock.fileno()), str(self.readypipein), self.logfile, self.bitbake_lock.name, self.sockname,  str(self.server_timeout or 0), str(self.xmlrpcinterface[0]), str(self.xmlrpcinterface[1]))
+
+def execServer(lockfd, readypipeinfd, lockname, sockname, server_timeout, xmlrpcinterface):
+
+    import bb.cookerdata
+    import bb.cooker
+
+    serverlog(start_log_format % (os.getpid(), datetime.datetime.now().strftime(start_log_datetime_format)))
+
+    try:
+        bitbake_lock = os.fdopen(lockfd, "w")
+
+        # Create server control socket
+        if os.path.exists(sockname):
+            os.unlink(sockname)
+
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        # AF_UNIX has path length issues so chdir here to workaround
+        cwd = os.getcwd()
         try:
-            self.cooker = bb.cooker.BBCooker(self.configuration, self.featureset)
+            os.chdir(os.path.dirname(sockname))
+            sock.bind(os.path.basename(sockname))
+        finally:
+            os.chdir(cwd)
+        sock.listen(1)
+
+        server = ProcessServer(bitbake_lock, lockname, sock, sockname, server_timeout, xmlrpcinterface)
+        writer = ConnectionWriter(readypipeinfd)
+        try:
+            featureset = []
+            cooker = bb.cooker.BBCooker(featureset, server.register_idle_function)
         except bb.BBHandledException:
             return None
         writer.send("r")
         writer.close()
-        server.cooker = self.cooker
-        server.server_timeout = self.configuration.server_timeout
-        server.xmlrpcinterface = self.configuration.xmlrpcinterface
-        print("Started bitbake server pid %d" % os.getpid())
-        sys.stdout.flush()
+        server.cooker = cooker
+        serverlog("Started bitbake server pid %d" % os.getpid())
 
-        server.start()
+        server.run()
+    finally:
+        # Flush any ,essages/errors to the logfile before exit
+        sys.stdout.flush()
+        sys.stderr.flush()
 
 def connectProcessServer(sockname, featureset):
     # Connect to socket
diff --git a/bitbake/lib/bb/siggen.py b/bitbake/lib/bb/siggen.py
index 94d1762d..0d88c6ec 100644
--- a/bitbake/lib/bb/siggen.py
+++ b/bitbake/lib/bb/siggen.py
@@ -39,6 +39,11 @@ class SignatureGenerator(object):
     """
     name = "noop"
 
+    # If the derived class supports multiconfig datacaches, set this to True
+    # The default is False for backward compatibility with derived signature
+    # generators that do not understand multiconfig caches
+    supports_multiconfig_datacaches = False
+
     def __init__(self, data):
         self.basehash = {}
         self.taskhash = {}
@@ -59,10 +64,10 @@ class SignatureGenerator(object):
     def get_unihash(self, tid):
         return self.taskhash[tid]
 
-    def prep_taskhash(self, tid, deps, dataCache):
+    def prep_taskhash(self, tid, deps, dataCaches):
         return
 
-    def get_taskhash(self, tid, deps, dataCache):
+    def get_taskhash(self, tid, deps, dataCaches):
         self.taskhash[tid] = hashlib.sha256(tid.encode("utf-8")).hexdigest()
         return self.taskhash[tid]
 
@@ -106,6 +111,38 @@ class SignatureGenerator(object):
     def set_setscene_tasks(self, setscene_tasks):
         return
 
+    @classmethod
+    def get_data_caches(cls, dataCaches, mc):
+        """
+        This function returns the datacaches that should be passed to signature
+        generator functions. If the signature generator supports multiconfig
+        caches, the entire dictionary of data caches is sent, otherwise a
+        special proxy is sent that support both index access to all
+        multiconfigs, and also direct access for the default multiconfig.
+
+        The proxy class allows code in this class itself to always use
+        multiconfig aware code (to ease maintenance), but derived classes that
+        are unaware of multiconfig data caches can still access the default
+        multiconfig as expected.
+
+        Do not override this function in derived classes; it will be removed in
+        the future when support for multiconfig data caches is mandatory
+        """
+        class DataCacheProxy(object):
+            def __init__(self):
+                pass
+
+            def __getitem__(self, key):
+                return dataCaches[key]
+
+            def __getattr__(self, name):
+                return getattr(dataCaches[mc], name)
+
+        if cls.supports_multiconfig_datacaches:
+            return dataCaches
+
+        return DataCacheProxy()
+
 class SignatureGeneratorBasic(SignatureGenerator):
     """
     """
@@ -201,7 +238,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
         self.lookupcache = {}
         self.taskdeps = {}
 
-    def rundep_check(self, fn, recipename, task, dep, depname, dataCache):
+    def rundep_check(self, fn, recipename, task, dep, depname, dataCaches):
         # Return True if we should keep the dependency, False to drop it
         # We only manipulate the dependencies for packages not in the whitelist
         if self.twl and not self.twl.search(recipename):
@@ -219,37 +256,40 @@ class SignatureGeneratorBasic(SignatureGenerator):
             pass
         return taint
 
-    def prep_taskhash(self, tid, deps, dataCache):
+    def prep_taskhash(self, tid, deps, dataCaches):
 
         (mc, _, task, fn) = bb.runqueue.split_tid_mcfn(tid)
 
-        self.basehash[tid] = dataCache.basetaskhash[tid]
+        self.basehash[tid] = dataCaches[mc].basetaskhash[tid]
         self.runtaskdeps[tid] = []
         self.file_checksum_values[tid] = []
-        recipename = dataCache.pkg_fn[fn]
+        recipename = dataCaches[mc].pkg_fn[fn]
 
         self.tidtopn[tid] = recipename
 
         for dep in sorted(deps, key=clean_basepath):
-            (depmc, _, deptaskname, depfn) = bb.runqueue.split_tid_mcfn(dep)
-            if mc != depmc:
+            (depmc, _, _, depmcfn) = bb.runqueue.split_tid_mcfn(dep)
+            depname = dataCaches[depmc].pkg_fn[depmcfn]
+            if not self.supports_multiconfig_datacaches and mc != depmc:
+                # If the signature generator doesn't understand multiconfig
+                # data caches, any dependency not in the same multiconfig must
+                # be skipped for backward compatibility
                 continue
-            depname = dataCache.pkg_fn[depfn]
-            if not self.rundep_check(fn, recipename, task, dep, depname, dataCache):
+            if not self.rundep_check(fn, recipename, task, dep, depname, dataCaches):
                 continue
             if dep not in self.taskhash:
                 bb.fatal("%s is not in taskhash, caller isn't calling in dependency order?" % dep)
             self.runtaskdeps[tid].append(dep)
 
-        if task in dataCache.file_checksums[fn]:
+        if task in dataCaches[mc].file_checksums[fn]:
             if self.checksum_cache:
-                checksums = self.checksum_cache.get_checksums(dataCache.file_checksums[fn][task], recipename, self.localdirsexclude)
+                checksums = self.checksum_cache.get_checksums(dataCaches[mc].file_checksums[fn][task], recipename, self.localdirsexclude)
             else:
-                checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename, self.localdirsexclude)
+                checksums = bb.fetch2.get_file_checksums(dataCaches[mc].file_checksums[fn][task], recipename, self.localdirsexclude)
             for (f,cs) in checksums:
                 self.file_checksum_values[tid].append((f,cs))
 
-        taskdep = dataCache.task_deps[fn]
+        taskdep = dataCaches[mc].task_deps[fn]
         if 'nostamp' in taskdep and task in taskdep['nostamp']:
             # Nostamp tasks need an implicit taint so that they force any dependent tasks to run
             if tid in self.taints and self.taints[tid].startswith("nostamp:"):
@@ -260,24 +300,18 @@ class SignatureGeneratorBasic(SignatureGenerator):
                 taint = str(uuid.uuid4())
                 self.taints[tid] = "nostamp:" + taint
 
-        taint = self.read_taint(fn, task, dataCache.stamp[fn])
+        taint = self.read_taint(fn, task, dataCaches[mc].stamp[fn])
         if taint:
             self.taints[tid] = taint
             logger.warning("%s is tainted from a forced run" % tid)
 
         return
 
-    def get_taskhash(self, tid, deps, dataCache):
+    def get_taskhash(self, tid, deps, dataCaches):
 
         data = self.basehash[tid]
         for dep in self.runtaskdeps[tid]:
-            if dep in self.unihash:
-                if self.unihash[dep] is None:
-                    data = data + self.taskhash[dep]
-                else:
-                    data = data + self.unihash[dep]
-            else:
-                data = data + self.get_unihash(dep)
+            data = data + self.get_unihash(dep)
 
         for (f, cs) in self.file_checksum_values[tid]:
             if cs:
@@ -318,7 +352,8 @@ class SignatureGeneratorBasic(SignatureGenerator):
         else:
             sigfile = stampbase + "." + task + ".sigbasedata" + "." + self.basehash[tid]
 
-        bb.utils.mkdirhier(os.path.dirname(sigfile))
+        with bb.utils.umask(0o002):
+            bb.utils.mkdirhier(os.path.dirname(sigfile))
 
         data = {}
         data['task'] = task
@@ -506,7 +541,7 @@ class SignatureGeneratorUniHashMixIn(object):
                 # is much more interesting, so it is reported at debug level 1
                 hashequiv_logger.debug((1, 2)[unihash == taskhash], 'Found unihash %s in place of %s for %s from %s' % (unihash, taskhash, tid, self.server))
             else:
-                hashequiv_logger.debug(2, 'No reported unihash for %s:%s from %s' % (tid, taskhash, self.server))
+                hashequiv_logger.debug2('No reported unihash for %s:%s from %s' % (tid, taskhash, self.server))
         except hashserv.client.HashConnectionError as e:
             bb.warn('Error contacting Hash Equivalence Server %s: %s' % (self.server, str(e)))
 
@@ -580,12 +615,12 @@ class SignatureGeneratorUniHashMixIn(object):
                 new_unihash = data['unihash']
 
                 if new_unihash != unihash:
-                    hashequiv_logger.debug(1, 'Task %s unihash changed %s -> %s by server %s' % (taskhash, unihash, new_unihash, self.server))
+                    hashequiv_logger.debug('Task %s unihash changed %s -> %s by server %s' % (taskhash, unihash, new_unihash, self.server))
                     bb.event.fire(bb.runqueue.taskUniHashUpdate(fn + ':do_' + task, new_unihash), d)
                     self.set_unihash(tid, new_unihash)
                     d.setVar('BB_UNIHASH', new_unihash)
                 else:
-                    hashequiv_logger.debug(1, 'Reported task %s as unihash %s to %s' % (taskhash, unihash, self.server))
+                    hashequiv_logger.debug('Reported task %s as unihash %s to %s' % (taskhash, unihash, self.server))
             except hashserv.client.HashConnectionError as e:
                 bb.warn('Error contacting Hash Equivalence Server %s: %s' % (self.server, str(e)))
         finally:
@@ -641,6 +676,12 @@ class SignatureGeneratorTestEquivHash(SignatureGeneratorUniHashMixIn, SignatureG
         self.server = data.getVar('BB_HASHSERVE')
         self.method = "sstate_output_hash"
 
+#
+# Dummy class used for bitbake-selftest
+#
+class SignatureGeneratorTestMulticonfigDepends(SignatureGeneratorBasicHash):
+    name = "TestMulticonfigDepends"
+    supports_multiconfig_datacaches = True
 
 def dump_this_task(outfile, d):
     import bb.parse
@@ -700,16 +741,26 @@ def list_inline_diff(oldlist, newlist, colors=None):
             ret.append(item)
     return '[%s]' % (', '.join(ret))
 
-def clean_basepath(a):
-    mc = None
-    if a.startswith("mc:"):
-        _, mc, a = a.split(":", 2)
-    b = a.rsplit("/", 2)[1] + '/' + a.rsplit("/", 2)[2]
-    if a.startswith("virtual:"):
-        b = b + ":" + a.rsplit(":", 1)[0]
-    if mc:
-        b = b + ":mc:" + mc
-    return b
+def clean_basepath(basepath):
+    basepath, dir, recipe_task = basepath.rsplit("/", 2)
+    cleaned = dir + '/' + recipe_task
+
+    if basepath[0] == '/':
+        return cleaned
+
+    if basepath.startswith("mc:") and basepath.count(':') >= 2:
+        mc, mc_name, basepath = basepath.split(":", 2)
+        mc_suffix = ':mc:' + mc_name
+    else:
+        mc_suffix = ''
+
+    # mc stuff now removed from basepath. Whatever was next, if present will be the first
+    # suffix. ':/', recipe path start, marks the end of this. Something like
+    # 'virtual:a[:b[:c]]:/path...' (b and c being optional)
+    if basepath[0] != '/':
+        cleaned += ':' + basepath.split(':/', 1)[0]
+
+    return cleaned + mc_suffix
 
 def clean_basepaths(a):
     b = {}
diff --git a/bitbake/lib/bb/taskdata.py b/bitbake/lib/bb/taskdata.py
index d13a1249..47bad6d1 100644
--- a/bitbake/lib/bb/taskdata.py
+++ b/bitbake/lib/bb/taskdata.py
@@ -21,8 +21,13 @@ def re_match_strings(target, strings):
     Whether or not the string 'target' matches
     any one string of the strings which can be regular expression string
     """
-    return any(name == target or re.match(name, target)
-               for name in strings)
+    for name in strings:
+        if name.startswith("^") or name.endswith("$"):
+            if re.match(name, target):
+                return True
+        elif name == target:
+            return True
+    return False
 
 class TaskEntry:
     def __init__(self):
@@ -126,7 +131,7 @@ class TaskData:
             for depend in dataCache.deps[fn]:
                 dependids.add(depend)
             self.depids[fn] = list(dependids)
-            logger.debug(2, "Added dependencies %s for %s", str(dataCache.deps[fn]), fn)
+            logger.debug2("Added dependencies %s for %s", str(dataCache.deps[fn]), fn)
 
         # Work out runtime dependencies
         if not fn in self.rdepids:
@@ -144,9 +149,9 @@ class TaskData:
                     rreclist.append(rdepend)
                     rdependids.add(rdepend)
             if rdependlist:
-                logger.debug(2, "Added runtime dependencies %s for %s", str(rdependlist), fn)
+                logger.debug2("Added runtime dependencies %s for %s", str(rdependlist), fn)
             if rreclist:
-                logger.debug(2, "Added runtime recommendations %s for %s", str(rreclist), fn)
+                logger.debug2("Added runtime recommendations %s for %s", str(rreclist), fn)
             self.rdepids[fn] = list(rdependids)
 
         for dep in self.depids[fn]:
@@ -373,7 +378,7 @@ class TaskData:
         for fn in eligible:
             if fn in self.failed_fns:
                 continue
-            logger.debug(2, "adding %s to satisfy %s", fn, item)
+            logger.debug2("adding %s to satisfy %s", fn, item)
             self.add_build_target(fn, item)
             self.add_tasks(fn, dataCache)
 
@@ -426,7 +431,7 @@ class TaskData:
         for fn in eligible:
             if fn in self.failed_fns:
                 continue
-            logger.debug(2, "adding '%s' to satisfy runtime '%s'", fn, item)
+            logger.debug2("adding '%s' to satisfy runtime '%s'", fn, item)
             self.add_runtime_target(fn, item)
             self.add_tasks(fn, dataCache)
 
@@ -441,7 +446,7 @@ class TaskData:
             return
         if not missing_list:
             missing_list = []
-        logger.debug(1, "File '%s' is unbuildable, removing...", fn)
+        logger.debug("File '%s' is unbuildable, removing...", fn)
         self.failed_fns.append(fn)
         for target in self.build_targets:
             if fn in self.build_targets[target]:
@@ -521,7 +526,7 @@ class TaskData:
                     added = added + 1
                 except (bb.providers.NoRProvider, bb.providers.MultipleRProvider):
                     self.remove_runtarget(target)
-            logger.debug(1, "Resolved " + str(added) + " extra dependencies")
+            logger.debug("Resolved " + str(added) + " extra dependencies")
             if added == 0:
                 break
         # self.dump_data()
@@ -544,38 +549,38 @@ class TaskData:
         """
         Dump some debug information on the internal data structures
         """
-        logger.debug(3, "build_names:")
-        logger.debug(3, ", ".join(self.build_targets))
+        logger.debug3("build_names:")
+        logger.debug3(", ".join(self.build_targets))
 
-        logger.debug(3, "run_names:")
-        logger.debug(3, ", ".join(self.run_targets))
+        logger.debug3("run_names:")
+        logger.debug3(", ".join(self.run_targets))
 
-        logger.debug(3, "build_targets:")
+        logger.debug3("build_targets:")
         for target in self.build_targets:
             targets = "None"
             if target in self.build_targets:
                 targets = self.build_targets[target]
-            logger.debug(3, " %s: %s", target, targets)
+            logger.debug3(" %s: %s", target, targets)
 
-        logger.debug(3, "run_targets:")
+        logger.debug3("run_targets:")
         for target in self.run_targets:
             targets = "None"
             if target in self.run_targets:
                 targets = self.run_targets[target]
-            logger.debug(3, " %s: %s", target, targets)
+            logger.debug3(" %s: %s", target, targets)
 
-        logger.debug(3, "tasks:")
+        logger.debug3("tasks:")
         for tid in self.taskentries:
-            logger.debug(3, " %s: %s %s %s",
+            logger.debug3(" %s: %s %s %s",
                        tid,
                        self.taskentries[tid].idepends,
                        self.taskentries[tid].irdepends,
                        self.taskentries[tid].tdepends)
 
-        logger.debug(3, "dependency ids (per fn):")
+        logger.debug3("dependency ids (per fn):")
         for fn in self.depids:
-            logger.debug(3, " %s: %s", fn, self.depids[fn])
+            logger.debug3(" %s: %s", fn, self.depids[fn])
 
-        logger.debug(3, "runtime dependency ids (per fn):")
+        logger.debug3("runtime dependency ids (per fn):")
         for fn in self.rdepids:
-            logger.debug(3, " %s: %s", fn, self.rdepids[fn])
+            logger.debug3(" %s: %s", fn, self.rdepids[fn])
diff --git a/bitbake/lib/bb/tests/codeparser.py b/bitbake/lib/bb/tests/codeparser.py
index 826a2d2f..f4852047 100644
--- a/bitbake/lib/bb/tests/codeparser.py
+++ b/bitbake/lib/bb/tests/codeparser.py
@@ -111,9 +111,9 @@ ${D}${libdir}/pkgconfig/*.pc
         self.assertExecs(set(["sed"]))
 
     def test_parameter_expansion_modifiers(self):
-        # - and + are also valid modifiers for parameter expansion, but are
+        # -,+ and : are also valid modifiers for parameter expansion, but are
         # valid characters in bitbake variable names, so are not included here
-        for i in ('=', ':-', ':=', '?', ':?', ':+', '#', '%', '##', '%%'):
+        for i in ('=', '?', '#', '%', '##', '%%'):
             name = "foo%sbar" % i
             self.parseExpression("${%s}" % name)
             self.assertNotIn(name, self.references)
diff --git a/bitbake/lib/bb/tests/color.py b/bitbake/lib/bb/tests/color.py
new file mode 100644
index 00000000..88dd2780
--- /dev/null
+++ b/bitbake/lib/bb/tests/color.py
@@ -0,0 +1,95 @@
+#
+# BitBake Test for ANSI color code filtering
+#
+# Copyright (C) 2020  Agilent Technologies, Inc.
+# Author: Chris Laplante <chris.laplante@agilent.com>
+#
+# SPDX-License-Identifier: MIT
+#
+
+import unittest
+import bb.progress
+import bb.data
+import bb.event
+from bb.progress import filter_color, filter_color_n
+import io
+import re
+
+
+class ProgressWatcher:
+    def __init__(self):
+        self._reports = []
+
+    def handle_event(self, event):
+        self._reports.append((event.progress, event.rate))
+
+    def reports(self):
+        return self._reports
+
+
+class ColorCodeTests(unittest.TestCase):
+    def setUp(self):
+        self.d = bb.data.init()
+        self._progress_watcher = ProgressWatcher()
+        bb.event.register("bb.build.TaskProgress", self._progress_watcher.handle_event, data=self.d)
+
+    def tearDown(self):
+        bb.event.remove("bb.build.TaskProgress", None)
+
+    def test_filter_color(self):
+        input_string = "^[[01;35m^[[K~~~~~~~~~~~~^~~~~~~~^[[m^[[K"
+        filtered = filter_color(input_string)
+        self.assertEqual(filtered, "~~~~~~~~~~~~^~~~~~~~")
+
+    def test_filter_color_n(self):
+        input_string = "^[[01;35m^[[K~~~~~~~~~~~~^~~~~~~~^[[m^[[K"
+        filtered, code_count = filter_color_n(input_string)
+        self.assertEqual(filtered, "~~~~~~~~~~~~^~~~~~~~")
+        self.assertEqual(code_count, 4)
+
+    def test_LineFilterProgressHandler_color_filtering(self):
+        class CustomProgressHandler(bb.progress.LineFilterProgressHandler):
+            PROGRESS_REGEX = re.compile(r"Progress: (?P<progress>\d+)%")
+
+            def writeline(self, line):
+                match = self.PROGRESS_REGEX.match(line)
+                if match:
+                    self.update(int(match.group("progress")))
+                    return False
+                return True
+
+        buffer = io.StringIO()
+        handler = CustomProgressHandler(self.d, buffer)
+        handler.write("Program output!\n")
+        handler.write("More output!\n")
+        handler.write("Progress: ^[[01;35m^[[K10^[[m^[[K%\n") # 10%
+        handler.write("Even more\n")
+        handler.write("^[[01;35m^[[KProgress: 50^[[m^[[K%\n") # 50%
+        handler.write("^[[01;35m^[[KProgress: 60^[[m^[[K%\n") # 60%
+        handler.write("Pro^[[01;35m^[[Kgress: ^[[m^[[K100%\n") # 100%
+
+        expected = [(10, None), (50, None), (60, None), (100, None)]
+        self.assertEqual(self._progress_watcher.reports(), expected)
+
+        self.assertEqual(buffer.getvalue(), "Program output!\nMore output!\nEven more\n")
+
+    def test_BasicProgressHandler_color_filtering(self):
+        buffer = io.StringIO()
+        handler = bb.progress.BasicProgressHandler(self.d, outfile=buffer)
+        handler.write("^[[01;35m^[[K1^[[m^[[K%\n") # 1%
+        handler.write("^[[01;35m^[[K2^[[m^[[K%\n") # 2%
+        handler.write("^[[01;35m^[[K10^[[m^[[K%\n") # 10%
+        handler.write("^[[01;35m^[[K100^[[m^[[K%\n") # 100%
+
+        expected = [(0, None), (1, None), (2, None), (10, None), (100, None)]
+        self.assertListEqual(self._progress_watcher.reports(), expected)
+
+    def test_OutOfProgressHandler_color_filtering(self):
+        buffer = io.StringIO()
+        handler = bb.progress.OutOfProgressHandler(self.d, r'(\d+) of (\d+)', outfile=buffer)
+        handler.write("^[[01;35m^[[KText text 1 of^[[m^[[K 5") # 1/5
+        handler.write("^[[01;35m^[[KText text 3 of^[[m^[[K 5") # 3/5
+        handler.write("^[[01;35m^[[KText text 5 of^[[m^[[K 5") # 5/5
+
+        expected = [(0, None), (20.0, None), (60.0, None), (100.0, None)]
+        self.assertListEqual(self._progress_watcher.reports(), expected)
diff --git a/bitbake/lib/bb/tests/cooker.py b/bitbake/lib/bb/tests/cooker.py
index 74c903f0..c82d4b7b 100644
--- a/bitbake/lib/bb/tests/cooker.py
+++ b/bitbake/lib/bb/tests/cooker.py
@@ -60,7 +60,7 @@ class CookerTest(unittest.TestCase):
         log_handler = LogHandler()
         logger.addHandler(log_handler)
         collection = bb.cooker.CookerCollectFiles(bbfile_config_priorities)
-        collection.collection_priorities(pkgfns, self.d)
+        collection.collection_priorities(pkgfns, pkgfns, self.d)
         logger.removeHandler(log_handler)
 
         # Should be empty (no generated messages)
diff --git a/bitbake/lib/bb/tests/cow.py b/bitbake/lib/bb/tests/cow.py
index bf6e79fc..75142649 100644
--- a/bitbake/lib/bb/tests/cow.py
+++ b/bitbake/lib/bb/tests/cow.py
@@ -4,9 +4,17 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 # Copyright 2006 Holger Freyther <freyther@handhelds.org>
+# Copyright (C) 2020  Agilent Technologies, Inc.
 #
 
+import io
+import re
+import sys
 import unittest
+import contextlib
+import collections
+
+from bb.COW import COWDictBase, COWSetBase, COWDictMeta, COWSetMeta
 
 
 class COWTestCase(unittest.TestCase):
@@ -14,11 +22,61 @@ class COWTestCase(unittest.TestCase):
     Test case for the COW module from mithro
     """
 
+    def setUp(self):
+        self._track_warnings = False
+        self._warning_file = io.StringIO()
+        self._unhandled_warnings = collections.deque()
+        COWDictBase.__warn__ = self._warning_file
+
+    def tearDown(self):
+        COWDictBase.__warn__ = sys.stderr
+        if self._track_warnings:
+            self._checkAllWarningsRead()
+
+    def trackWarnings(self):
+        self._track_warnings = True
+
+    def _collectWarnings(self):
+        self._warning_file.seek(0)
+        for warning in self._warning_file:
+            self._unhandled_warnings.append(warning.rstrip("\n"))
+        self._warning_file.truncate(0)
+        self._warning_file.seek(0)
+
+    def _checkAllWarningsRead(self):
+        self._collectWarnings()
+        self.assertSequenceEqual(self._unhandled_warnings, [])
+
+    @contextlib.contextmanager
+    def checkReportsWarning(self, expected_warning):
+        self._checkAllWarningsRead()
+        yield
+        self._collectWarnings()
+        warning = self._unhandled_warnings.popleft()
+        self.assertEqual(warning, expected_warning)
+
+    def checkStrOutput(self, obj, expected_levels, expected_keys):
+        if obj.__class__ is COWDictMeta:
+            expected_class_name = "COWDict"
+        elif obj.__class__ is COWSetMeta:
+            expected_class_name = "COWSet"
+        else:
+            self.fail("obj is of unknown type {0}".format(type(obj)))
+        s = str(obj)
+        regex = re.compile(r"<(\w+) Level: (\d+) Current Keys: (\d+)>")
+        match = regex.match(s)
+        self.assertIsNotNone(match, "bad str output: '{0}'".format(s))
+        class_name = match.group(1)
+        self.assertEqual(class_name, expected_class_name)
+        levels = int(match.group(2))
+        self.assertEqual(levels, expected_levels, "wrong # levels in str: '{0}'".format(s))
+        keys = int(match.group(3))
+        self.assertEqual(keys, expected_keys, "wrong # keys in str: '{0}'".format(s))
+
     def testGetSet(self):
         """
         Test and set
         """
-        from bb.COW import COWDictBase
         a = COWDictBase.copy()
 
         self.assertEqual(False, 'a' in a)
@@ -27,16 +85,14 @@ class COWTestCase(unittest.TestCase):
         a['b'] = 'b'
         self.assertEqual(True, 'a' in a)
         self.assertEqual(True, 'b' in a)
-        self.assertEqual('a', a['a'] )
-        self.assertEqual('b', a['b'] )
+        self.assertEqual('a', a['a'])
+        self.assertEqual('b', a['b'])
 
     def testCopyCopy(self):
         """
         Test the copy of copies
         """
 
-        from bb.COW import COWDictBase
-
         # create two COW dict 'instances'
         b = COWDictBase.copy()
         c = COWDictBase.copy()
@@ -94,30 +150,168 @@ class COWTestCase(unittest.TestCase):
         self.assertEqual(False, 'e' in b_2)
 
     def testCow(self):
-        from bb.COW import COWDictBase
+        self.trackWarnings()
+
         c = COWDictBase.copy()
         c['123'] = 1027
         c['other'] = 4711
-        c['d'] = { 'abc' : 10, 'bcd' : 20 }
+        c['d'] = {'abc': 10, 'bcd': 20}
 
         copy = c.copy()
 
         self.assertEqual(1027, c['123'])
         self.assertEqual(4711, c['other'])
-        self.assertEqual({'abc':10, 'bcd':20}, c['d'])
+        self.assertEqual({'abc': 10, 'bcd': 20}, c['d'])
         self.assertEqual(1027, copy['123'])
         self.assertEqual(4711, copy['other'])
-        self.assertEqual({'abc':10, 'bcd':20}, copy['d'])
+        with self.checkReportsWarning("Warning: Doing a copy because d is a mutable type."):
+            self.assertEqual({'abc': 10, 'bcd': 20}, copy['d'])
 
         # cow it now
         copy['123'] = 1028
         copy['other'] = 4712
         copy['d']['abc'] = 20
 
-
         self.assertEqual(1027, c['123'])
         self.assertEqual(4711, c['other'])
-        self.assertEqual({'abc':10, 'bcd':20}, c['d'])
+        self.assertEqual({'abc': 10, 'bcd': 20}, c['d'])
         self.assertEqual(1028, copy['123'])
         self.assertEqual(4712, copy['other'])
-        self.assertEqual({'abc':20, 'bcd':20}, copy['d'])
+        self.assertEqual({'abc': 20, 'bcd': 20}, copy['d'])
+
+    def testOriginalTestSuite(self):
+        # This test suite is a port of the original one from COW.py
+        self.trackWarnings()
+
+        a = COWDictBase.copy()
+        self.checkStrOutput(a, 1, 0)
+
+        a['a'] = 'a'
+        a['b'] = 'b'
+        a['dict'] = {}
+        self.checkStrOutput(a, 1, 4)  # 4th member is dict__mutable__
+
+        b = a.copy()
+        self.checkStrOutput(b, 2, 0)
+        b['c'] = 'b'
+        self.checkStrOutput(b, 2, 1)
+
+        with self.checkReportsWarning("Warning: If you aren't going to change any of the values call with True."):
+            self.assertListEqual(list(a.iteritems()),
+                                 [('a', 'a'),
+                                  ('b', 'b'),
+                                  ('dict', {})
+                                  ])
+
+        with self.checkReportsWarning("Warning: If you aren't going to change any of the values call with True."):
+            b_gen = b.iteritems()
+        self.assertTupleEqual(next(b_gen), ('a', 'a'))
+        self.assertTupleEqual(next(b_gen), ('b', 'b'))
+        self.assertTupleEqual(next(b_gen), ('c', 'b'))
+        with self.checkReportsWarning("Warning: Doing a copy because dict is a mutable type."):
+            self.assertTupleEqual(next(b_gen), ('dict', {}))
+        with self.assertRaises(StopIteration):
+            next(b_gen)
+
+        b['dict']['a'] = 'b'
+        b['a'] = 'c'
+
+        self.checkStrOutput(a, 1, 4)
+        self.checkStrOutput(b, 2, 3)
+
+        with self.checkReportsWarning("Warning: If you aren't going to change any of the values call with True."):
+            self.assertListEqual(list(a.iteritems()),
+                                 [('a', 'a'),
+                                  ('b', 'b'),
+                                  ('dict', {})
+                                  ])
+
+        with self.checkReportsWarning("Warning: If you aren't going to change any of the values call with True."):
+            b_gen = b.iteritems()
+        self.assertTupleEqual(next(b_gen), ('a', 'c'))
+        self.assertTupleEqual(next(b_gen), ('b', 'b'))
+        self.assertTupleEqual(next(b_gen), ('c', 'b'))
+        self.assertTupleEqual(next(b_gen), ('dict', {'a': 'b'}))
+        with self.assertRaises(StopIteration):
+            next(b_gen)
+
+        with self.assertRaises(KeyError):
+            print(b["dict2"])
+
+        a['set'] = COWSetBase()
+        a['set'].add("o1")
+        a['set'].add("o1")
+        a['set'].add("o2")
+        self.assertSetEqual(set(a['set'].itervalues()), {"o1", "o2"})
+        self.assertSetEqual(set(b['set'].itervalues()), {"o1", "o2"})
+
+        b['set'].add('o3')
+        self.assertSetEqual(set(a['set'].itervalues()), {"o1", "o2"})
+        self.assertSetEqual(set(b['set'].itervalues()), {"o1", "o2", "o3"})
+
+        a['set2'] = set()
+        a['set2'].add("o1")
+        a['set2'].add("o1")
+        a['set2'].add("o2")
+
+        # We don't expect 'a' to change anymore
+        def check_a():
+            with self.checkReportsWarning("Warning: If you aren't going to change any of the values call with True."):
+                a_gen = a.iteritems()
+                self.assertTupleEqual(next(a_gen), ('a', 'a'))
+            self.assertTupleEqual(next(a_gen), ('b', 'b'))
+            self.assertTupleEqual(next(a_gen), ('dict', {}))
+            self.assertTupleEqual(next(a_gen), ('set2', {'o1', 'o2'}))
+            a_sub_set = next(a_gen)
+            self.assertEqual(a_sub_set[0], 'set')
+            self.checkStrOutput(a_sub_set[1], 1, 2)
+            self.assertSetEqual(set(a_sub_set[1].itervalues()), {'o1', 'o2'})
+
+        check_a()
+
+        b_gen = b.iteritems(readonly=True)
+        self.assertTupleEqual(next(b_gen), ('a', 'c'))
+        self.assertTupleEqual(next(b_gen), ('b', 'b'))
+        self.assertTupleEqual(next(b_gen), ('c', 'b'))
+        self.assertTupleEqual(next(b_gen), ('dict', {'a': 'b'}))
+        self.assertTupleEqual(next(b_gen), ('set2', {'o1', 'o2'}))
+        b_sub_set = next(b_gen)
+        self.assertEqual(b_sub_set[0], 'set')
+        self.checkStrOutput(b_sub_set[1], 2, 1)
+        self.assertSetEqual(set(b_sub_set[1].itervalues()), {'o1', 'o2', 'o3'})
+
+        del b['b']
+        with self.assertRaises(KeyError):
+            print(b['b'])
+        self.assertFalse('b' in b)
+
+        check_a()
+
+        b.__revertitem__('b')
+        check_a()
+        self.assertEqual(b['b'], 'b')
+        self.assertTrue('b' in b)
+
+        b.__revertitem__('dict')
+        check_a()
+
+        b_gen = b.iteritems(readonly=True)
+        self.assertTupleEqual(next(b_gen), ('a', 'c'))
+        self.assertTupleEqual(next(b_gen), ('b', 'b'))
+        self.assertTupleEqual(next(b_gen), ('c', 'b'))
+        self.assertTupleEqual(next(b_gen), ('dict', {}))
+        self.assertTupleEqual(next(b_gen), ('set2', {'o1', 'o2'}))
+        b_sub_set = next(b_gen)
+        self.assertEqual(b_sub_set[0], 'set')
+        self.checkStrOutput(b_sub_set[1], 2, 1)
+        self.assertSetEqual(set(b_sub_set[1].itervalues()), {'o1', 'o2', 'o3'})
+
+        self.checkStrOutput(a, 1, 6)
+        self.checkStrOutput(b, 2, 3)
+
+    def testSetMethods(self):
+        s = COWSetBase()
+        with self.assertRaises(TypeError):
+            print(s.iteritems())
+        with self.assertRaises(TypeError):
+            print(s.iterkeys())
diff --git a/bitbake/lib/bb/tests/data.py b/bitbake/lib/bb/tests/data.py
index 5f195047..1d4a64b1 100644
--- a/bitbake/lib/bb/tests/data.py
+++ b/bitbake/lib/bb/tests/data.py
@@ -12,6 +12,7 @@ import bb
 import bb.data
 import bb.parse
 import logging
+import os
 
 class LogRecord():
     def __enter__(self):
diff --git a/bitbake/lib/bb/tests/event.py b/bitbake/lib/bb/tests/event.py
index 9229b63d..9ca7e9bc 100644
--- a/bitbake/lib/bb/tests/event.py
+++ b/bitbake/lib/bb/tests/event.py
@@ -6,17 +6,18 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
-import unittest
-import bb
-import logging
-import bb.compat
-import bb.event
+import collections
 import importlib
+import logging
+import pickle
 import threading
 import time
-import pickle
+import unittest
 from unittest.mock import Mock
 from unittest.mock import call
+
+import bb
+import bb.event
 from bb.msg import BBLogFormatter
 
 
@@ -75,7 +76,7 @@ class EventHandlingTest(unittest.TestCase):
 
     def _create_test_handlers(self):
         """ Method used to create a test handler ordered dictionary """
-        test_handlers = bb.compat.OrderedDict()
+        test_handlers = collections.OrderedDict()
         test_handlers["handler1"] = self._test_process.handler1
         test_handlers["handler2"] = self._test_process.handler2
         return test_handlers
@@ -96,7 +97,7 @@ class EventHandlingTest(unittest.TestCase):
 
     def test_clean_class_handlers(self):
         """ Test clean_class_handlers method """
-        cleanDict = bb.compat.OrderedDict()
+        cleanDict = collections.OrderedDict()
         self.assertEqual(cleanDict,
                          bb.event.clean_class_handlers())
 
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.23/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.23/index.html
index a251c981..b3d9244b 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.23/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.23/index.html
@@ -1,45 +1,45 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.23/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.23/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     31-Jul-2013 12:35       -
-<a href="libmount-docs/">libmount-docs/</a>                                     31-Jul-2013 12:39       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2942
-<a href="util-linux-2.23-rc1.tar.bz2">util-linux-2.23-rc1.tar.bz2</a>                        22-Mar-2013 12:48      5M
-<a href="util-linux-2.23-rc1.tar.gz">util-linux-2.23-rc1.tar.gz</a>                         22-Mar-2013 12:48      7M
-<a href="util-linux-2.23-rc1.tar.sign">util-linux-2.23-rc1.tar.sign</a>                       22-Mar-2013 12:48     836
-<a href="util-linux-2.23-rc1.tar.xz">util-linux-2.23-rc1.tar.xz</a>                         22-Mar-2013 12:48      3M
-<a href="util-linux-2.23-rc2.tar.bz2">util-linux-2.23-rc2.tar.bz2</a>                        10-Apr-2013 22:14      5M
-<a href="util-linux-2.23-rc2.tar.gz">util-linux-2.23-rc2.tar.gz</a>                         10-Apr-2013 22:14      7M
-<a href="util-linux-2.23-rc2.tar.sign">util-linux-2.23-rc2.tar.sign</a>                       10-Apr-2013 22:14     836
-<a href="util-linux-2.23-rc2.tar.xz">util-linux-2.23-rc2.tar.xz</a>                         10-Apr-2013 22:14      3M
-<a href="util-linux-2.23.1.tar.bz2">util-linux-2.23.1.tar.bz2</a>                          28-May-2013 09:57      5M
-<a href="util-linux-2.23.1.tar.gz">util-linux-2.23.1.tar.gz</a>                           28-May-2013 09:57      7M
-<a href="util-linux-2.23.1.tar.sign">util-linux-2.23.1.tar.sign</a>                         28-May-2013 09:57     836
-<a href="util-linux-2.23.1.tar.xz">util-linux-2.23.1.tar.xz</a>                           28-May-2013 09:57      3M
-<a href="util-linux-2.23.2.tar.bz2">util-linux-2.23.2.tar.bz2</a>                          31-Jul-2013 12:40      5M
-<a href="util-linux-2.23.2.tar.gz">util-linux-2.23.2.tar.gz</a>                           31-Jul-2013 12:40      7M
-<a href="util-linux-2.23.2.tar.sign">util-linux-2.23.2.tar.sign</a>                         31-Jul-2013 12:40     836
-<a href="util-linux-2.23.2.tar.xz">util-linux-2.23.2.tar.xz</a>                           31-Jul-2013 12:40      3M
-<a href="util-linux-2.23.tar.bz2">util-linux-2.23.tar.bz2</a>                            25-Apr-2013 10:48      5M
-<a href="util-linux-2.23.tar.gz">util-linux-2.23.tar.gz</a>                             25-Apr-2013 10:48      7M
-<a href="util-linux-2.23.tar.sign">util-linux-2.23.tar.sign</a>                           25-Apr-2013 10:48     836
-<a href="util-linux-2.23.tar.xz">util-linux-2.23.tar.xz</a>                             25-Apr-2013 10:48      3M
-<a href="v2.23-ChangeLog">v2.23-ChangeLog</a>                                    25-Apr-2013 10:48     19K
-<a href="v2.23-ChangeLog.sign">v2.23-ChangeLog.sign</a>                               25-Apr-2013 10:48     836
-<a href="v2.23-ReleaseNotes">v2.23-ReleaseNotes</a>                                 25-Apr-2013 10:48     53K
-<a href="v2.23-ReleaseNotes.sign">v2.23-ReleaseNotes.sign</a>                            25-Apr-2013 10:48     836
-<a href="v2.23-rc1-ChangeLog">v2.23-rc1-ChangeLog</a>                                22-Mar-2013 12:48    361K
-<a href="v2.23-rc1-ChangeLog.sign">v2.23-rc1-ChangeLog.sign</a>                           22-Mar-2013 12:48     836
-<a href="v2.23-rc2-ChangeLog">v2.23-rc2-ChangeLog</a>                                10-Apr-2013 22:14     80K
-<a href="v2.23-rc2-ChangeLog.sign">v2.23-rc2-ChangeLog.sign</a>                           10-Apr-2013 22:14     836
-<a href="v2.23.1-ChangeLog">v2.23.1-ChangeLog</a>                                  28-May-2013 09:57     13K
-<a href="v2.23.1-ChangeLog.sign">v2.23.1-ChangeLog.sign</a>                             28-May-2013 09:57     836
-<a href="v2.23.1-ReleaseNotes">v2.23.1-ReleaseNotes</a>                               28-May-2013 09:58    1448
-<a href="v2.23.1-ReleaseNotes.sign">v2.23.1-ReleaseNotes.sign</a>                          28-May-2013 09:58     836
-<a href="v2.23.2-ChangeLog">v2.23.2-ChangeLog</a>                                  31-Jul-2013 12:40     23K
-<a href="v2.23.2-ChangeLog.sign">v2.23.2-ChangeLog.sign</a>                             31-Jul-2013 12:40     836
-<a href="v2.23.2-ReleaseNotes">v2.23.2-ReleaseNotes</a>                               31-Jul-2013 12:40    2582
-<a href="v2.23.2-ReleaseNotes.sign">v2.23.2-ReleaseNotes.sign</a>                          31-Jul-2013 12:40     836
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.23/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.23/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     31-Jul-2013 12:35       -
+<a href="libmount-docs/">libmount-docs/</a>                                     31-Jul-2013 12:39       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2942
+<a href="util-linux-2.23-rc1.tar.bz2">util-linux-2.23-rc1.tar.bz2</a>                        22-Mar-2013 12:48      5M
+<a href="util-linux-2.23-rc1.tar.gz">util-linux-2.23-rc1.tar.gz</a>                         22-Mar-2013 12:48      7M
+<a href="util-linux-2.23-rc1.tar.sign">util-linux-2.23-rc1.tar.sign</a>                       22-Mar-2013 12:48     836
+<a href="util-linux-2.23-rc1.tar.xz">util-linux-2.23-rc1.tar.xz</a>                         22-Mar-2013 12:48      3M
+<a href="util-linux-2.23-rc2.tar.bz2">util-linux-2.23-rc2.tar.bz2</a>                        10-Apr-2013 22:14      5M
+<a href="util-linux-2.23-rc2.tar.gz">util-linux-2.23-rc2.tar.gz</a>                         10-Apr-2013 22:14      7M
+<a href="util-linux-2.23-rc2.tar.sign">util-linux-2.23-rc2.tar.sign</a>                       10-Apr-2013 22:14     836
+<a href="util-linux-2.23-rc2.tar.xz">util-linux-2.23-rc2.tar.xz</a>                         10-Apr-2013 22:14      3M
+<a href="util-linux-2.23.1.tar.bz2">util-linux-2.23.1.tar.bz2</a>                          28-May-2013 09:57      5M
+<a href="util-linux-2.23.1.tar.gz">util-linux-2.23.1.tar.gz</a>                           28-May-2013 09:57      7M
+<a href="util-linux-2.23.1.tar.sign">util-linux-2.23.1.tar.sign</a>                         28-May-2013 09:57     836
+<a href="util-linux-2.23.1.tar.xz">util-linux-2.23.1.tar.xz</a>                           28-May-2013 09:57      3M
+<a href="util-linux-2.23.2.tar.bz2">util-linux-2.23.2.tar.bz2</a>                          31-Jul-2013 12:40      5M
+<a href="util-linux-2.23.2.tar.gz">util-linux-2.23.2.tar.gz</a>                           31-Jul-2013 12:40      7M
+<a href="util-linux-2.23.2.tar.sign">util-linux-2.23.2.tar.sign</a>                         31-Jul-2013 12:40     836
+<a href="util-linux-2.23.2.tar.xz">util-linux-2.23.2.tar.xz</a>                           31-Jul-2013 12:40      3M
+<a href="util-linux-2.23.tar.bz2">util-linux-2.23.tar.bz2</a>                            25-Apr-2013 10:48      5M
+<a href="util-linux-2.23.tar.gz">util-linux-2.23.tar.gz</a>                             25-Apr-2013 10:48      7M
+<a href="util-linux-2.23.tar.sign">util-linux-2.23.tar.sign</a>                           25-Apr-2013 10:48     836
+<a href="util-linux-2.23.tar.xz">util-linux-2.23.tar.xz</a>                             25-Apr-2013 10:48      3M
+<a href="v2.23-ChangeLog">v2.23-ChangeLog</a>                                    25-Apr-2013 10:48     19K
+<a href="v2.23-ChangeLog.sign">v2.23-ChangeLog.sign</a>                               25-Apr-2013 10:48     836
+<a href="v2.23-ReleaseNotes">v2.23-ReleaseNotes</a>                                 25-Apr-2013 10:48     53K
+<a href="v2.23-ReleaseNotes.sign">v2.23-ReleaseNotes.sign</a>                            25-Apr-2013 10:48     836
+<a href="v2.23-rc1-ChangeLog">v2.23-rc1-ChangeLog</a>                                22-Mar-2013 12:48    361K
+<a href="v2.23-rc1-ChangeLog.sign">v2.23-rc1-ChangeLog.sign</a>                           22-Mar-2013 12:48     836
+<a href="v2.23-rc2-ChangeLog">v2.23-rc2-ChangeLog</a>                                10-Apr-2013 22:14     80K
+<a href="v2.23-rc2-ChangeLog.sign">v2.23-rc2-ChangeLog.sign</a>                           10-Apr-2013 22:14     836
+<a href="v2.23.1-ChangeLog">v2.23.1-ChangeLog</a>                                  28-May-2013 09:57     13K
+<a href="v2.23.1-ChangeLog.sign">v2.23.1-ChangeLog.sign</a>                             28-May-2013 09:57     836
+<a href="v2.23.1-ReleaseNotes">v2.23.1-ReleaseNotes</a>                               28-May-2013 09:58    1448
+<a href="v2.23.1-ReleaseNotes.sign">v2.23.1-ReleaseNotes.sign</a>                          28-May-2013 09:58     836
+<a href="v2.23.2-ChangeLog">v2.23.2-ChangeLog</a>                                  31-Jul-2013 12:40     23K
+<a href="v2.23.2-ChangeLog.sign">v2.23.2-ChangeLog.sign</a>                             31-Jul-2013 12:40     836
+<a href="v2.23.2-ReleaseNotes">v2.23.2-ReleaseNotes</a>                               31-Jul-2013 12:40    2582
+<a href="v2.23.2-ReleaseNotes.sign">v2.23.2-ReleaseNotes.sign</a>                          31-Jul-2013 12:40     836
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.24/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.24/index.html
index 486791d6..4afb4625 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.24/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.24/index.html
@@ -1,43 +1,43 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.24/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.24/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     24-Apr-2014 10:15       -
-<a href="libmount-docs/">libmount-docs/</a>                                     24-Apr-2014 10:17       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2758
-<a href="util-linux-2.24-rc1.tar.bz2">util-linux-2.24-rc1.tar.bz2</a>                        27-Sep-2013 12:54      5M
-<a href="util-linux-2.24-rc1.tar.gz">util-linux-2.24-rc1.tar.gz</a>                         27-Sep-2013 12:54      7M
-<a href="util-linux-2.24-rc1.tar.sign">util-linux-2.24-rc1.tar.sign</a>                       27-Sep-2013 12:54     836
-<a href="util-linux-2.24-rc1.tar.xz">util-linux-2.24-rc1.tar.xz</a>                         27-Sep-2013 12:54      3M
-<a href="util-linux-2.24-rc2.tar.bz2">util-linux-2.24-rc2.tar.bz2</a>                        11-Oct-2013 11:37      5M
-<a href="util-linux-2.24-rc2.tar.gz">util-linux-2.24-rc2.tar.gz</a>                         11-Oct-2013 11:37      7M
-<a href="util-linux-2.24-rc2.tar.sign">util-linux-2.24-rc2.tar.sign</a>                       11-Oct-2013 11:37     836
-<a href="util-linux-2.24-rc2.tar.xz">util-linux-2.24-rc2.tar.xz</a>                         11-Oct-2013 11:37      3M
-<a href="util-linux-2.24.1.tar.gz">util-linux-2.24.1.tar.gz</a>                           20-Jan-2014 13:33      7M
-<a href="util-linux-2.24.1.tar.sign">util-linux-2.24.1.tar.sign</a>                         20-Jan-2014 13:33     819
-<a href="util-linux-2.24.1.tar.xz">util-linux-2.24.1.tar.xz</a>                           20-Jan-2014 13:33      3M
-<a href="util-linux-2.24.2.tar.gz">util-linux-2.24.2.tar.gz</a>                           24-Apr-2014 10:17      7M
-<a href="util-linux-2.24.2.tar.sign">util-linux-2.24.2.tar.sign</a>                         24-Apr-2014 10:17     819
-<a href="util-linux-2.24.2.tar.xz">util-linux-2.24.2.tar.xz</a>                           24-Apr-2014 10:17      3M
-<a href="util-linux-2.24.tar.bz2">util-linux-2.24.tar.bz2</a>                            21-Oct-2013 13:49      5M
-<a href="util-linux-2.24.tar.gz">util-linux-2.24.tar.gz</a>                             21-Oct-2013 13:49      7M
-<a href="util-linux-2.24.tar.sign">util-linux-2.24.tar.sign</a>                           21-Oct-2013 13:49     836
-<a href="util-linux-2.24.tar.xz">util-linux-2.24.tar.xz</a>                             21-Oct-2013 13:49      3M
-<a href="v2.24-ChangeLog">v2.24-ChangeLog</a>                                    21-Oct-2013 13:49     22K
-<a href="v2.24-ChangeLog.sign">v2.24-ChangeLog.sign</a>                               21-Oct-2013 13:49     836
-<a href="v2.24-ReleaseNotes">v2.24-ReleaseNotes</a>                                 21-Oct-2013 13:49     44K
-<a href="v2.24-ReleaseNotes.sign">v2.24-ReleaseNotes.sign</a>                            21-Oct-2013 13:49     836
-<a href="v2.24-rc1-ChangeLog">v2.24-rc1-ChangeLog</a>                                27-Sep-2013 12:54    292K
-<a href="v2.24-rc1-ChangeLog.sign">v2.24-rc1-ChangeLog.sign</a>                           27-Sep-2013 12:54     836
-<a href="v2.24-rc2-ChangeLog">v2.24-rc2-ChangeLog</a>                                11-Oct-2013 11:37     42K
-<a href="v2.24-rc2-ChangeLog.sign">v2.24-rc2-ChangeLog.sign</a>                           11-Oct-2013 11:37     836
-<a href="v2.24.1-ChangeLog">v2.24.1-ChangeLog</a>                                  20-Jan-2014 13:33     38K
-<a href="v2.24.1-ChangeLog.sign">v2.24.1-ChangeLog.sign</a>                             20-Jan-2014 13:33     819
-<a href="v2.24.1-ReleaseNotes">v2.24.1-ReleaseNotes</a>                               20-Jan-2014 13:33    4449
-<a href="v2.24.1-ReleaseNotes.sign">v2.24.1-ReleaseNotes.sign</a>                          20-Jan-2014 13:33     819
-<a href="v2.24.2-ChangeLog">v2.24.2-ChangeLog</a>                                  24-Apr-2014 10:17     47K
-<a href="v2.24.2-ChangeLog.sign">v2.24.2-ChangeLog.sign</a>                             24-Apr-2014 10:17     819
-<a href="v2.24.2-ReleaseNotes">v2.24.2-ReleaseNotes</a>                               24-Apr-2014 10:18    5748
-<a href="v2.24.2-ReleaseNotes.sign">v2.24.2-ReleaseNotes.sign</a>                          24-Apr-2014 10:18     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.24/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.24/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     24-Apr-2014 10:15       -
+<a href="libmount-docs/">libmount-docs/</a>                                     24-Apr-2014 10:17       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2758
+<a href="util-linux-2.24-rc1.tar.bz2">util-linux-2.24-rc1.tar.bz2</a>                        27-Sep-2013 12:54      5M
+<a href="util-linux-2.24-rc1.tar.gz">util-linux-2.24-rc1.tar.gz</a>                         27-Sep-2013 12:54      7M
+<a href="util-linux-2.24-rc1.tar.sign">util-linux-2.24-rc1.tar.sign</a>                       27-Sep-2013 12:54     836
+<a href="util-linux-2.24-rc1.tar.xz">util-linux-2.24-rc1.tar.xz</a>                         27-Sep-2013 12:54      3M
+<a href="util-linux-2.24-rc2.tar.bz2">util-linux-2.24-rc2.tar.bz2</a>                        11-Oct-2013 11:37      5M
+<a href="util-linux-2.24-rc2.tar.gz">util-linux-2.24-rc2.tar.gz</a>                         11-Oct-2013 11:37      7M
+<a href="util-linux-2.24-rc2.tar.sign">util-linux-2.24-rc2.tar.sign</a>                       11-Oct-2013 11:37     836
+<a href="util-linux-2.24-rc2.tar.xz">util-linux-2.24-rc2.tar.xz</a>                         11-Oct-2013 11:37      3M
+<a href="util-linux-2.24.1.tar.gz">util-linux-2.24.1.tar.gz</a>                           20-Jan-2014 13:33      7M
+<a href="util-linux-2.24.1.tar.sign">util-linux-2.24.1.tar.sign</a>                         20-Jan-2014 13:33     819
+<a href="util-linux-2.24.1.tar.xz">util-linux-2.24.1.tar.xz</a>                           20-Jan-2014 13:33      3M
+<a href="util-linux-2.24.2.tar.gz">util-linux-2.24.2.tar.gz</a>                           24-Apr-2014 10:17      7M
+<a href="util-linux-2.24.2.tar.sign">util-linux-2.24.2.tar.sign</a>                         24-Apr-2014 10:17     819
+<a href="util-linux-2.24.2.tar.xz">util-linux-2.24.2.tar.xz</a>                           24-Apr-2014 10:17      3M
+<a href="util-linux-2.24.tar.bz2">util-linux-2.24.tar.bz2</a>                            21-Oct-2013 13:49      5M
+<a href="util-linux-2.24.tar.gz">util-linux-2.24.tar.gz</a>                             21-Oct-2013 13:49      7M
+<a href="util-linux-2.24.tar.sign">util-linux-2.24.tar.sign</a>                           21-Oct-2013 13:49     836
+<a href="util-linux-2.24.tar.xz">util-linux-2.24.tar.xz</a>                             21-Oct-2013 13:49      3M
+<a href="v2.24-ChangeLog">v2.24-ChangeLog</a>                                    21-Oct-2013 13:49     22K
+<a href="v2.24-ChangeLog.sign">v2.24-ChangeLog.sign</a>                               21-Oct-2013 13:49     836
+<a href="v2.24-ReleaseNotes">v2.24-ReleaseNotes</a>                                 21-Oct-2013 13:49     44K
+<a href="v2.24-ReleaseNotes.sign">v2.24-ReleaseNotes.sign</a>                            21-Oct-2013 13:49     836
+<a href="v2.24-rc1-ChangeLog">v2.24-rc1-ChangeLog</a>                                27-Sep-2013 12:54    292K
+<a href="v2.24-rc1-ChangeLog.sign">v2.24-rc1-ChangeLog.sign</a>                           27-Sep-2013 12:54     836
+<a href="v2.24-rc2-ChangeLog">v2.24-rc2-ChangeLog</a>                                11-Oct-2013 11:37     42K
+<a href="v2.24-rc2-ChangeLog.sign">v2.24-rc2-ChangeLog.sign</a>                           11-Oct-2013 11:37     836
+<a href="v2.24.1-ChangeLog">v2.24.1-ChangeLog</a>                                  20-Jan-2014 13:33     38K
+<a href="v2.24.1-ChangeLog.sign">v2.24.1-ChangeLog.sign</a>                             20-Jan-2014 13:33     819
+<a href="v2.24.1-ReleaseNotes">v2.24.1-ReleaseNotes</a>                               20-Jan-2014 13:33    4449
+<a href="v2.24.1-ReleaseNotes.sign">v2.24.1-ReleaseNotes.sign</a>                          20-Jan-2014 13:33     819
+<a href="v2.24.2-ChangeLog">v2.24.2-ChangeLog</a>                                  24-Apr-2014 10:17     47K
+<a href="v2.24.2-ChangeLog.sign">v2.24.2-ChangeLog.sign</a>                             24-Apr-2014 10:17     819
+<a href="v2.24.2-ReleaseNotes">v2.24.2-ReleaseNotes</a>                               24-Apr-2014 10:18    5748
+<a href="v2.24.2-ReleaseNotes.sign">v2.24.2-ReleaseNotes.sign</a>                          24-Apr-2014 10:18     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.25/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.25/index.html
index b3fdadc8..9516c3b1 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.25/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.25/index.html
@@ -1,46 +1,46 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.25/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.25/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     24-Oct-2014 13:05       -
-<a href="libmount-docs/">libmount-docs/</a>                                     24-Oct-2014 13:06       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 24-Oct-2014 13:08       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2758
-<a href="util-linux-2.25-rc1.tar.gz">util-linux-2.25-rc1.tar.gz</a>                         18-Jun-2014 13:33      7M
-<a href="util-linux-2.25-rc1.tar.sign">util-linux-2.25-rc1.tar.sign</a>                       18-Jun-2014 13:33     819
-<a href="util-linux-2.25-rc1.tar.xz">util-linux-2.25-rc1.tar.xz</a>                         18-Jun-2014 13:33      3M
-<a href="util-linux-2.25-rc2.tar.gz">util-linux-2.25-rc2.tar.gz</a>                         02-Jul-2014 10:02      7M
-<a href="util-linux-2.25-rc2.tar.sign">util-linux-2.25-rc2.tar.sign</a>                       02-Jul-2014 10:02     819
-<a href="util-linux-2.25-rc2.tar.xz">util-linux-2.25-rc2.tar.xz</a>                         02-Jul-2014 10:02      3M
-<a href="util-linux-2.25.1-rc1.tar.gz">util-linux-2.25.1-rc1.tar.gz</a>                       27-Aug-2014 13:18      8M
-<a href="util-linux-2.25.1-rc1.tar.sign">util-linux-2.25.1-rc1.tar.sign</a>                     27-Aug-2014 13:18     819
-<a href="util-linux-2.25.1-rc1.tar.xz">util-linux-2.25.1-rc1.tar.xz</a>                       27-Aug-2014 13:18      4M
-<a href="util-linux-2.25.1.tar.gz">util-linux-2.25.1.tar.gz</a>                           03-Sep-2014 10:41      8M
-<a href="util-linux-2.25.1.tar.sign">util-linux-2.25.1.tar.sign</a>                         03-Sep-2014 10:41     819
-<a href="util-linux-2.25.1.tar.xz">util-linux-2.25.1.tar.xz</a>                           03-Sep-2014 10:41      4M
-<a href="util-linux-2.25.2.tar.gz">util-linux-2.25.2.tar.gz</a>                           24-Oct-2014 13:08      8M
-<a href="util-linux-2.25.2.tar.sign">util-linux-2.25.2.tar.sign</a>                         24-Oct-2014 13:08     819
-<a href="util-linux-2.25.2.tar.xz">util-linux-2.25.2.tar.xz</a>                           24-Oct-2014 13:08      4M
-<a href="util-linux-2.25.tar.gz">util-linux-2.25.tar.gz</a>                             22-Jul-2014 09:50      8M
-<a href="util-linux-2.25.tar.sign">util-linux-2.25.tar.sign</a>                           22-Jul-2014 09:50     819
-<a href="util-linux-2.25.tar.xz">util-linux-2.25.tar.xz</a>                             22-Jul-2014 09:50      4M
-<a href="v2.25-ChangeLog">v2.25-ChangeLog</a>                                    22-Jul-2014 09:50     41K
-<a href="v2.25-ChangeLog.sign">v2.25-ChangeLog.sign</a>                               22-Jul-2014 09:50     819
-<a href="v2.25-ReleaseNotes">v2.25-ReleaseNotes</a>                                 22-Jul-2014 09:50     61K
-<a href="v2.25-ReleaseNotes.sign">v2.25-ReleaseNotes.sign</a>                            22-Jul-2014 09:50     819
-<a href="v2.25-rc1-ChangeLog">v2.25-rc1-ChangeLog</a>                                18-Jun-2014 13:33    489K
-<a href="v2.25-rc1-ChangeLog.sign">v2.25-rc1-ChangeLog.sign</a>                           18-Jun-2014 13:33     819
-<a href="v2.25-rc2-ChangeLog">v2.25-rc2-ChangeLog</a>                                02-Jul-2014 10:02     27K
-<a href="v2.25-rc2-ChangeLog.sign">v2.25-rc2-ChangeLog.sign</a>                           02-Jul-2014 10:02     819
-<a href="v2.25.1-ChangeLog">v2.25.1-ChangeLog</a>                                  03-Sep-2014 10:41    5816
-<a href="v2.25.1-ChangeLog.sign">v2.25.1-ChangeLog.sign</a>                             03-Sep-2014 10:41     819
-<a href="v2.25.1-ReleaseNotes">v2.25.1-ReleaseNotes</a>                               03-Sep-2014 10:52    3220
-<a href="v2.25.1-ReleaseNotes.sign">v2.25.1-ReleaseNotes.sign</a>                          03-Sep-2014 10:52     819
-<a href="v2.25.1-rc1-ChangeLog">v2.25.1-rc1-ChangeLog</a>                              27-Aug-2014 13:18     22K
-<a href="v2.25.1-rc1-ChangeLog.sign">v2.25.1-rc1-ChangeLog.sign</a>                         27-Aug-2014 13:18     819
-<a href="v2.25.2-ChangeLog">v2.25.2-ChangeLog</a>                                  24-Oct-2014 13:08     26K
-<a href="v2.25.2-ChangeLog.sign">v2.25.2-ChangeLog.sign</a>                             24-Oct-2014 13:08     819
-<a href="v2.25.2-ReleaseNotes">v2.25.2-ReleaseNotes</a>                               24-Oct-2014 13:08    3016
-<a href="v2.25.2-ReleaseNotes.sign">v2.25.2-ReleaseNotes.sign</a>                          24-Oct-2014 13:08     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.25/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.25/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     24-Oct-2014 13:05       -
+<a href="libmount-docs/">libmount-docs/</a>                                     24-Oct-2014 13:06       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 24-Oct-2014 13:08       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:53    2758
+<a href="util-linux-2.25-rc1.tar.gz">util-linux-2.25-rc1.tar.gz</a>                         18-Jun-2014 13:33      7M
+<a href="util-linux-2.25-rc1.tar.sign">util-linux-2.25-rc1.tar.sign</a>                       18-Jun-2014 13:33     819
+<a href="util-linux-2.25-rc1.tar.xz">util-linux-2.25-rc1.tar.xz</a>                         18-Jun-2014 13:33      3M
+<a href="util-linux-2.25-rc2.tar.gz">util-linux-2.25-rc2.tar.gz</a>                         02-Jul-2014 10:02      7M
+<a href="util-linux-2.25-rc2.tar.sign">util-linux-2.25-rc2.tar.sign</a>                       02-Jul-2014 10:02     819
+<a href="util-linux-2.25-rc2.tar.xz">util-linux-2.25-rc2.tar.xz</a>                         02-Jul-2014 10:02      3M
+<a href="util-linux-2.25.1-rc1.tar.gz">util-linux-2.25.1-rc1.tar.gz</a>                       27-Aug-2014 13:18      8M
+<a href="util-linux-2.25.1-rc1.tar.sign">util-linux-2.25.1-rc1.tar.sign</a>                     27-Aug-2014 13:18     819
+<a href="util-linux-2.25.1-rc1.tar.xz">util-linux-2.25.1-rc1.tar.xz</a>                       27-Aug-2014 13:18      4M
+<a href="util-linux-2.25.1.tar.gz">util-linux-2.25.1.tar.gz</a>                           03-Sep-2014 10:41      8M
+<a href="util-linux-2.25.1.tar.sign">util-linux-2.25.1.tar.sign</a>                         03-Sep-2014 10:41     819
+<a href="util-linux-2.25.1.tar.xz">util-linux-2.25.1.tar.xz</a>                           03-Sep-2014 10:41      4M
+<a href="util-linux-2.25.2.tar.gz">util-linux-2.25.2.tar.gz</a>                           24-Oct-2014 13:08      8M
+<a href="util-linux-2.25.2.tar.sign">util-linux-2.25.2.tar.sign</a>                         24-Oct-2014 13:08     819
+<a href="util-linux-2.25.2.tar.xz">util-linux-2.25.2.tar.xz</a>                           24-Oct-2014 13:08      4M
+<a href="util-linux-2.25.tar.gz">util-linux-2.25.tar.gz</a>                             22-Jul-2014 09:50      8M
+<a href="util-linux-2.25.tar.sign">util-linux-2.25.tar.sign</a>                           22-Jul-2014 09:50     819
+<a href="util-linux-2.25.tar.xz">util-linux-2.25.tar.xz</a>                             22-Jul-2014 09:50      4M
+<a href="v2.25-ChangeLog">v2.25-ChangeLog</a>                                    22-Jul-2014 09:50     41K
+<a href="v2.25-ChangeLog.sign">v2.25-ChangeLog.sign</a>                               22-Jul-2014 09:50     819
+<a href="v2.25-ReleaseNotes">v2.25-ReleaseNotes</a>                                 22-Jul-2014 09:50     61K
+<a href="v2.25-ReleaseNotes.sign">v2.25-ReleaseNotes.sign</a>                            22-Jul-2014 09:50     819
+<a href="v2.25-rc1-ChangeLog">v2.25-rc1-ChangeLog</a>                                18-Jun-2014 13:33    489K
+<a href="v2.25-rc1-ChangeLog.sign">v2.25-rc1-ChangeLog.sign</a>                           18-Jun-2014 13:33     819
+<a href="v2.25-rc2-ChangeLog">v2.25-rc2-ChangeLog</a>                                02-Jul-2014 10:02     27K
+<a href="v2.25-rc2-ChangeLog.sign">v2.25-rc2-ChangeLog.sign</a>                           02-Jul-2014 10:02     819
+<a href="v2.25.1-ChangeLog">v2.25.1-ChangeLog</a>                                  03-Sep-2014 10:41    5816
+<a href="v2.25.1-ChangeLog.sign">v2.25.1-ChangeLog.sign</a>                             03-Sep-2014 10:41     819
+<a href="v2.25.1-ReleaseNotes">v2.25.1-ReleaseNotes</a>                               03-Sep-2014 10:52    3220
+<a href="v2.25.1-ReleaseNotes.sign">v2.25.1-ReleaseNotes.sign</a>                          03-Sep-2014 10:52     819
+<a href="v2.25.1-rc1-ChangeLog">v2.25.1-rc1-ChangeLog</a>                              27-Aug-2014 13:18     22K
+<a href="v2.25.1-rc1-ChangeLog.sign">v2.25.1-rc1-ChangeLog.sign</a>                         27-Aug-2014 13:18     819
+<a href="v2.25.2-ChangeLog">v2.25.2-ChangeLog</a>                                  24-Oct-2014 13:08     26K
+<a href="v2.25.2-ChangeLog.sign">v2.25.2-ChangeLog.sign</a>                             24-Oct-2014 13:08     819
+<a href="v2.25.2-ReleaseNotes">v2.25.2-ReleaseNotes</a>                               24-Oct-2014 13:08    3016
+<a href="v2.25.2-ReleaseNotes.sign">v2.25.2-ReleaseNotes.sign</a>                          24-Oct-2014 13:08     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.26/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.26/index.html
index cd15132e..b9914895 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.26/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.26/index.html
@@ -1,42 +1,42 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.26/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.26/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     30-Apr-2015 10:38       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     30-Apr-2015 10:40       -
-<a href="libmount-docs/">libmount-docs/</a>                                     30-Apr-2015 10:42       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 30-Apr-2015 10:43       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:54    2480
-<a href="util-linux-2.26-rc1.tar.gz">util-linux-2.26-rc1.tar.gz</a>                         14-Jan-2015 13:14      8M
-<a href="util-linux-2.26-rc1.tar.sign">util-linux-2.26-rc1.tar.sign</a>                       14-Jan-2015 13:14     819
-<a href="util-linux-2.26-rc1.tar.xz">util-linux-2.26-rc1.tar.xz</a>                         14-Jan-2015 13:14      4M
-<a href="util-linux-2.26-rc2.tar.gz">util-linux-2.26-rc2.tar.gz</a>                         04-Feb-2015 11:49      8M
-<a href="util-linux-2.26-rc2.tar.sign">util-linux-2.26-rc2.tar.sign</a>                       04-Feb-2015 11:49     819
-<a href="util-linux-2.26-rc2.tar.xz">util-linux-2.26-rc2.tar.xz</a>                         04-Feb-2015 11:49      4M
-<a href="util-linux-2.26.1.tar.gz">util-linux-2.26.1.tar.gz</a>                           13-Mar-2015 14:23      8M
-<a href="util-linux-2.26.1.tar.sign">util-linux-2.26.1.tar.sign</a>                         13-Mar-2015 14:23     819
-<a href="util-linux-2.26.1.tar.xz">util-linux-2.26.1.tar.xz</a>                           13-Mar-2015 14:23      4M
-<a href="util-linux-2.26.2.tar.gz">util-linux-2.26.2.tar.gz</a>                           30-Apr-2015 10:44      8M
-<a href="util-linux-2.26.2.tar.sign">util-linux-2.26.2.tar.sign</a>                         30-Apr-2015 10:44     819
-<a href="util-linux-2.26.2.tar.xz">util-linux-2.26.2.tar.xz</a>                           30-Apr-2015 10:44      4M
-<a href="util-linux-2.26.tar.gz">util-linux-2.26.tar.gz</a>                             19-Feb-2015 12:47      8M
-<a href="util-linux-2.26.tar.sign">util-linux-2.26.tar.sign</a>                           19-Feb-2015 12:47     819
-<a href="util-linux-2.26.tar.xz">util-linux-2.26.tar.xz</a>                             19-Feb-2015 12:47      4M
-<a href="v2.26-ChangeLog">v2.26-ChangeLog</a>                                    19-Feb-2015 12:47     30K
-<a href="v2.26-ChangeLog.sign">v2.26-ChangeLog.sign</a>                               19-Feb-2015 12:47     819
-<a href="v2.26-ReleaseNotes">v2.26-ReleaseNotes</a>                                 19-Feb-2015 12:47     51K
-<a href="v2.26-ReleaseNotes.sign">v2.26-ReleaseNotes.sign</a>                            19-Feb-2015 12:47     819
-<a href="v2.26-rc1-ChangeLog">v2.26-rc1-ChangeLog</a>                                14-Jan-2015 13:14    360K
-<a href="v2.26-rc1-ChangeLog.sign">v2.26-rc1-ChangeLog.sign</a>                           14-Jan-2015 13:14     819
-<a href="v2.26-rc2-ChangeLog">v2.26-rc2-ChangeLog</a>                                04-Feb-2015 11:50     51K
-<a href="v2.26-rc2-ChangeLog.sign">v2.26-rc2-ChangeLog.sign</a>                           04-Feb-2015 11:50     819
-<a href="v2.26.1-ChangeLog">v2.26.1-ChangeLog</a>                                  13-Mar-2015 14:23     32K
-<a href="v2.26.1-ChangeLog.sign">v2.26.1-ChangeLog.sign</a>                             13-Mar-2015 14:23     819
-<a href="v2.26.1-ReleaseNotes">v2.26.1-ReleaseNotes</a>                               13-Mar-2015 14:23    2944
-<a href="v2.26.1-ReleaseNotes.sign">v2.26.1-ReleaseNotes.sign</a>                          13-Mar-2015 14:23     819
-<a href="v2.26.2-ChangeLog">v2.26.2-ChangeLog</a>                                  30-Apr-2015 10:44     58K
-<a href="v2.26.2-ChangeLog.sign">v2.26.2-ChangeLog.sign</a>                             30-Apr-2015 10:44     819
-<a href="v2.26.2-ReleaseNotes">v2.26.2-ReleaseNotes</a>                               30-Apr-2015 10:44    5834
-<a href="v2.26.2-ReleaseNotes.sign">v2.26.2-ReleaseNotes.sign</a>                          30-Apr-2015 10:44     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.26/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.26/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     30-Apr-2015 10:38       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     30-Apr-2015 10:40       -
+<a href="libmount-docs/">libmount-docs/</a>                                     30-Apr-2015 10:42       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 30-Apr-2015 10:43       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:54    2480
+<a href="util-linux-2.26-rc1.tar.gz">util-linux-2.26-rc1.tar.gz</a>                         14-Jan-2015 13:14      8M
+<a href="util-linux-2.26-rc1.tar.sign">util-linux-2.26-rc1.tar.sign</a>                       14-Jan-2015 13:14     819
+<a href="util-linux-2.26-rc1.tar.xz">util-linux-2.26-rc1.tar.xz</a>                         14-Jan-2015 13:14      4M
+<a href="util-linux-2.26-rc2.tar.gz">util-linux-2.26-rc2.tar.gz</a>                         04-Feb-2015 11:49      8M
+<a href="util-linux-2.26-rc2.tar.sign">util-linux-2.26-rc2.tar.sign</a>                       04-Feb-2015 11:49     819
+<a href="util-linux-2.26-rc2.tar.xz">util-linux-2.26-rc2.tar.xz</a>                         04-Feb-2015 11:49      4M
+<a href="util-linux-2.26.1.tar.gz">util-linux-2.26.1.tar.gz</a>                           13-Mar-2015 14:23      8M
+<a href="util-linux-2.26.1.tar.sign">util-linux-2.26.1.tar.sign</a>                         13-Mar-2015 14:23     819
+<a href="util-linux-2.26.1.tar.xz">util-linux-2.26.1.tar.xz</a>                           13-Mar-2015 14:23      4M
+<a href="util-linux-2.26.2.tar.gz">util-linux-2.26.2.tar.gz</a>                           30-Apr-2015 10:44      8M
+<a href="util-linux-2.26.2.tar.sign">util-linux-2.26.2.tar.sign</a>                         30-Apr-2015 10:44     819
+<a href="util-linux-2.26.2.tar.xz">util-linux-2.26.2.tar.xz</a>                           30-Apr-2015 10:44      4M
+<a href="util-linux-2.26.tar.gz">util-linux-2.26.tar.gz</a>                             19-Feb-2015 12:47      8M
+<a href="util-linux-2.26.tar.sign">util-linux-2.26.tar.sign</a>                           19-Feb-2015 12:47     819
+<a href="util-linux-2.26.tar.xz">util-linux-2.26.tar.xz</a>                             19-Feb-2015 12:47      4M
+<a href="v2.26-ChangeLog">v2.26-ChangeLog</a>                                    19-Feb-2015 12:47     30K
+<a href="v2.26-ChangeLog.sign">v2.26-ChangeLog.sign</a>                               19-Feb-2015 12:47     819
+<a href="v2.26-ReleaseNotes">v2.26-ReleaseNotes</a>                                 19-Feb-2015 12:47     51K
+<a href="v2.26-ReleaseNotes.sign">v2.26-ReleaseNotes.sign</a>                            19-Feb-2015 12:47     819
+<a href="v2.26-rc1-ChangeLog">v2.26-rc1-ChangeLog</a>                                14-Jan-2015 13:14    360K
+<a href="v2.26-rc1-ChangeLog.sign">v2.26-rc1-ChangeLog.sign</a>                           14-Jan-2015 13:14     819
+<a href="v2.26-rc2-ChangeLog">v2.26-rc2-ChangeLog</a>                                04-Feb-2015 11:50     51K
+<a href="v2.26-rc2-ChangeLog.sign">v2.26-rc2-ChangeLog.sign</a>                           04-Feb-2015 11:50     819
+<a href="v2.26.1-ChangeLog">v2.26.1-ChangeLog</a>                                  13-Mar-2015 14:23     32K
+<a href="v2.26.1-ChangeLog.sign">v2.26.1-ChangeLog.sign</a>                             13-Mar-2015 14:23     819
+<a href="v2.26.1-ReleaseNotes">v2.26.1-ReleaseNotes</a>                               13-Mar-2015 14:23    2944
+<a href="v2.26.1-ReleaseNotes.sign">v2.26.1-ReleaseNotes.sign</a>                          13-Mar-2015 14:23     819
+<a href="v2.26.2-ChangeLog">v2.26.2-ChangeLog</a>                                  30-Apr-2015 10:44     58K
+<a href="v2.26.2-ChangeLog.sign">v2.26.2-ChangeLog.sign</a>                             30-Apr-2015 10:44     819
+<a href="v2.26.2-ReleaseNotes">v2.26.2-ReleaseNotes</a>                               30-Apr-2015 10:44    5834
+<a href="v2.26.2-ReleaseNotes.sign">v2.26.2-ReleaseNotes.sign</a>                          30-Apr-2015 10:44     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.27/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.27/index.html
index b7b21606..14eb3683 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.27/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.27/index.html
@@ -1,35 +1,35 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.27/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.27/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     02-Nov-2015 11:01       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     02-Nov-2015 11:03       -
-<a href="libmount-docs/">libmount-docs/</a>                                     02-Nov-2015 11:04       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 02-Nov-2015 11:06       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:54    2127
-<a href="util-linux-2.27-rc1.tar.gz">util-linux-2.27-rc1.tar.gz</a>                         31-Jul-2015 11:01      8M
-<a href="util-linux-2.27-rc1.tar.sign">util-linux-2.27-rc1.tar.sign</a>                       31-Jul-2015 11:01     819
-<a href="util-linux-2.27-rc1.tar.xz">util-linux-2.27-rc1.tar.xz</a>                         31-Jul-2015 11:01      4M
-<a href="util-linux-2.27-rc2.tar.gz">util-linux-2.27-rc2.tar.gz</a>                         24-Aug-2015 11:04      8M
-<a href="util-linux-2.27-rc2.tar.sign">util-linux-2.27-rc2.tar.sign</a>                       24-Aug-2015 11:04     819
-<a href="util-linux-2.27-rc2.tar.xz">util-linux-2.27-rc2.tar.xz</a>                         24-Aug-2015 11:04      4M
-<a href="util-linux-2.27.1.tar.gz">util-linux-2.27.1.tar.gz</a>                           02-Nov-2015 11:06      8M
-<a href="util-linux-2.27.1.tar.sign">util-linux-2.27.1.tar.sign</a>                         02-Nov-2015 11:06     819
-<a href="util-linux-2.27.1.tar.xz">util-linux-2.27.1.tar.xz</a>                           02-Nov-2015 11:06      4M
-<a href="util-linux-2.27.tar.gz">util-linux-2.27.tar.gz</a>                             07-Sep-2015 08:17      8M
-<a href="util-linux-2.27.tar.sign">util-linux-2.27.tar.sign</a>                           07-Sep-2015 08:17     819
-<a href="util-linux-2.27.tar.xz">util-linux-2.27.tar.xz</a>                             07-Sep-2015 08:17      4M
-<a href="v2.27-ChangeLog">v2.27-ChangeLog</a>                                    07-Sep-2015 08:17     21K
-<a href="v2.27-ChangeLog.sign">v2.27-ChangeLog.sign</a>                               07-Sep-2015 08:17     819
-<a href="v2.27-ReleaseNotes">v2.27-ReleaseNotes</a>                                 07-Sep-2015 08:17     35K
-<a href="v2.27-ReleaseNotes.sign">v2.27-ReleaseNotes.sign</a>                            07-Sep-2015 08:17     819
-<a href="v2.27-rc1-ChangeLog">v2.27-rc1-ChangeLog</a>                                31-Jul-2015 11:01    263K
-<a href="v2.27-rc1-ChangeLog.sign">v2.27-rc1-ChangeLog.sign</a>                           31-Jul-2015 11:01     819
-<a href="v2.27-rc2-ChangeLog">v2.27-rc2-ChangeLog</a>                                24-Aug-2015 11:04     38K
-<a href="v2.27-rc2-ChangeLog.sign">v2.27-rc2-ChangeLog.sign</a>                           24-Aug-2015 11:04     819
-<a href="v2.27.1-ChangeLog">v2.27.1-ChangeLog</a>                                  02-Nov-2015 11:06     18K
-<a href="v2.27.1-ChangeLog.sign">v2.27.1-ChangeLog.sign</a>                             02-Nov-2015 11:06     819
-<a href="v2.27.1-ReleaseNotes">v2.27.1-ReleaseNotes</a>                               02-Nov-2015 11:06    2107
-<a href="v2.27.1-ReleaseNotes.sign">v2.27.1-ReleaseNotes.sign</a>                          02-Nov-2015 11:06     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.27/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.27/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     02-Nov-2015 11:01       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     02-Nov-2015 11:03       -
+<a href="libmount-docs/">libmount-docs/</a>                                     02-Nov-2015 11:04       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 02-Nov-2015 11:06       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:54    2127
+<a href="util-linux-2.27-rc1.tar.gz">util-linux-2.27-rc1.tar.gz</a>                         31-Jul-2015 11:01      8M
+<a href="util-linux-2.27-rc1.tar.sign">util-linux-2.27-rc1.tar.sign</a>                       31-Jul-2015 11:01     819
+<a href="util-linux-2.27-rc1.tar.xz">util-linux-2.27-rc1.tar.xz</a>                         31-Jul-2015 11:01      4M
+<a href="util-linux-2.27-rc2.tar.gz">util-linux-2.27-rc2.tar.gz</a>                         24-Aug-2015 11:04      8M
+<a href="util-linux-2.27-rc2.tar.sign">util-linux-2.27-rc2.tar.sign</a>                       24-Aug-2015 11:04     819
+<a href="util-linux-2.27-rc2.tar.xz">util-linux-2.27-rc2.tar.xz</a>                         24-Aug-2015 11:04      4M
+<a href="util-linux-2.27.1.tar.gz">util-linux-2.27.1.tar.gz</a>                           02-Nov-2015 11:06      8M
+<a href="util-linux-2.27.1.tar.sign">util-linux-2.27.1.tar.sign</a>                         02-Nov-2015 11:06     819
+<a href="util-linux-2.27.1.tar.xz">util-linux-2.27.1.tar.xz</a>                           02-Nov-2015 11:06      4M
+<a href="util-linux-2.27.tar.gz">util-linux-2.27.tar.gz</a>                             07-Sep-2015 08:17      8M
+<a href="util-linux-2.27.tar.sign">util-linux-2.27.tar.sign</a>                           07-Sep-2015 08:17     819
+<a href="util-linux-2.27.tar.xz">util-linux-2.27.tar.xz</a>                             07-Sep-2015 08:17      4M
+<a href="v2.27-ChangeLog">v2.27-ChangeLog</a>                                    07-Sep-2015 08:17     21K
+<a href="v2.27-ChangeLog.sign">v2.27-ChangeLog.sign</a>                               07-Sep-2015 08:17     819
+<a href="v2.27-ReleaseNotes">v2.27-ReleaseNotes</a>                                 07-Sep-2015 08:17     35K
+<a href="v2.27-ReleaseNotes.sign">v2.27-ReleaseNotes.sign</a>                            07-Sep-2015 08:17     819
+<a href="v2.27-rc1-ChangeLog">v2.27-rc1-ChangeLog</a>                                31-Jul-2015 11:01    263K
+<a href="v2.27-rc1-ChangeLog.sign">v2.27-rc1-ChangeLog.sign</a>                           31-Jul-2015 11:01     819
+<a href="v2.27-rc2-ChangeLog">v2.27-rc2-ChangeLog</a>                                24-Aug-2015 11:04     38K
+<a href="v2.27-rc2-ChangeLog.sign">v2.27-rc2-ChangeLog.sign</a>                           24-Aug-2015 11:04     819
+<a href="v2.27.1-ChangeLog">v2.27.1-ChangeLog</a>                                  02-Nov-2015 11:06     18K
+<a href="v2.27.1-ChangeLog.sign">v2.27.1-ChangeLog.sign</a>                             02-Nov-2015 11:06     819
+<a href="v2.27.1-ReleaseNotes">v2.27.1-ReleaseNotes</a>                               02-Nov-2015 11:06    2107
+<a href="v2.27.1-ReleaseNotes.sign">v2.27.1-ReleaseNotes.sign</a>                          02-Nov-2015 11:06     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.28/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.28/index.html
index f2370edf..4bba6b47 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.28/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.28/index.html
@@ -1,42 +1,42 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.28/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.28/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     07-Sep-2016 12:00       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     07-Sep-2016 12:02       -
-<a href="libmount-docs/">libmount-docs/</a>                                     07-Sep-2016 12:04       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 07-Sep-2016 12:06       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:55    2480
-<a href="util-linux-2.28-rc1.tar.gz">util-linux-2.28-rc1.tar.gz</a>                         11-Mar-2016 11:45      8M
-<a href="util-linux-2.28-rc1.tar.sign">util-linux-2.28-rc1.tar.sign</a>                       11-Mar-2016 11:45     819
-<a href="util-linux-2.28-rc1.tar.xz">util-linux-2.28-rc1.tar.xz</a>                         11-Mar-2016 11:45      4M
-<a href="util-linux-2.28-rc2.tar.gz">util-linux-2.28-rc2.tar.gz</a>                         29-Mar-2016 09:04      8M
-<a href="util-linux-2.28-rc2.tar.sign">util-linux-2.28-rc2.tar.sign</a>                       29-Mar-2016 09:04     819
-<a href="util-linux-2.28-rc2.tar.xz">util-linux-2.28-rc2.tar.xz</a>                         29-Mar-2016 09:04      4M
-<a href="util-linux-2.28.1.tar.gz">util-linux-2.28.1.tar.gz</a>                           11-Aug-2016 10:09      9M
-<a href="util-linux-2.28.1.tar.sign">util-linux-2.28.1.tar.sign</a>                         11-Aug-2016 10:09     819
-<a href="util-linux-2.28.1.tar.xz">util-linux-2.28.1.tar.xz</a>                           11-Aug-2016 10:09      4M
-<a href="util-linux-2.28.2.tar.gz">util-linux-2.28.2.tar.gz</a>                           07-Sep-2016 12:06      9M
-<a href="util-linux-2.28.2.tar.sign">util-linux-2.28.2.tar.sign</a>                         07-Sep-2016 12:06     819
-<a href="util-linux-2.28.2.tar.xz">util-linux-2.28.2.tar.xz</a>                           07-Sep-2016 12:06      4M
-<a href="util-linux-2.28.tar.gz">util-linux-2.28.tar.gz</a>                             12-Apr-2016 11:26      8M
-<a href="util-linux-2.28.tar.sign">util-linux-2.28.tar.sign</a>                           12-Apr-2016 11:26     819
-<a href="util-linux-2.28.tar.xz">util-linux-2.28.tar.xz</a>                             12-Apr-2016 11:26      4M
-<a href="v2.28-ChangeLog">v2.28-ChangeLog</a>                                    12-Apr-2016 11:26     13K
-<a href="v2.28-ChangeLog.sign">v2.28-ChangeLog.sign</a>                               12-Apr-2016 11:26     819
-<a href="v2.28-ReleaseNotes">v2.28-ReleaseNotes</a>                                 12-Apr-2016 11:26     33K
-<a href="v2.28-ReleaseNotes.sign">v2.28-ReleaseNotes.sign</a>                            12-Apr-2016 11:26     819
-<a href="v2.28-rc1-ChangeLog">v2.28-rc1-ChangeLog</a>                                11-Mar-2016 11:45    269K
-<a href="v2.28-rc1-ChangeLog.sign">v2.28-rc1-ChangeLog.sign</a>                           11-Mar-2016 11:45     819
-<a href="v2.28-rc2-ChangeLog">v2.28-rc2-ChangeLog</a>                                29-Mar-2016 09:04     52K
-<a href="v2.28-rc2-ChangeLog.sign">v2.28-rc2-ChangeLog.sign</a>                           29-Mar-2016 09:04     819
-<a href="v2.28.1-ChangeLog">v2.28.1-ChangeLog</a>                                  11-Aug-2016 10:09     37K
-<a href="v2.28.1-ChangeLog.sign">v2.28.1-ChangeLog.sign</a>                             11-Aug-2016 10:09     819
-<a href="v2.28.1-ReleaseNotes">v2.28.1-ReleaseNotes</a>                               11-Aug-2016 10:09    3748
-<a href="v2.28.1-ReleaseNotes.sign">v2.28.1-ReleaseNotes.sign</a>                          11-Aug-2016 10:09     819
-<a href="v2.28.2-ChangeLog">v2.28.2-ChangeLog</a>                                  07-Sep-2016 12:06    8900
-<a href="v2.28.2-ChangeLog.sign">v2.28.2-ChangeLog.sign</a>                             07-Sep-2016 12:06     819
-<a href="v2.28.2-ReleaseNotes">v2.28.2-ReleaseNotes</a>                               07-Sep-2016 12:06    1161
-<a href="v2.28.2-ReleaseNotes.sign">v2.28.2-ReleaseNotes.sign</a>                          07-Sep-2016 12:06     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.28/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.28/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     07-Sep-2016 12:00       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     07-Sep-2016 12:02       -
+<a href="libmount-docs/">libmount-docs/</a>                                     07-Sep-2016 12:04       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 07-Sep-2016 12:06       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:55    2480
+<a href="util-linux-2.28-rc1.tar.gz">util-linux-2.28-rc1.tar.gz</a>                         11-Mar-2016 11:45      8M
+<a href="util-linux-2.28-rc1.tar.sign">util-linux-2.28-rc1.tar.sign</a>                       11-Mar-2016 11:45     819
+<a href="util-linux-2.28-rc1.tar.xz">util-linux-2.28-rc1.tar.xz</a>                         11-Mar-2016 11:45      4M
+<a href="util-linux-2.28-rc2.tar.gz">util-linux-2.28-rc2.tar.gz</a>                         29-Mar-2016 09:04      8M
+<a href="util-linux-2.28-rc2.tar.sign">util-linux-2.28-rc2.tar.sign</a>                       29-Mar-2016 09:04     819
+<a href="util-linux-2.28-rc2.tar.xz">util-linux-2.28-rc2.tar.xz</a>                         29-Mar-2016 09:04      4M
+<a href="util-linux-2.28.1.tar.gz">util-linux-2.28.1.tar.gz</a>                           11-Aug-2016 10:09      9M
+<a href="util-linux-2.28.1.tar.sign">util-linux-2.28.1.tar.sign</a>                         11-Aug-2016 10:09     819
+<a href="util-linux-2.28.1.tar.xz">util-linux-2.28.1.tar.xz</a>                           11-Aug-2016 10:09      4M
+<a href="util-linux-2.28.2.tar.gz">util-linux-2.28.2.tar.gz</a>                           07-Sep-2016 12:06      9M
+<a href="util-linux-2.28.2.tar.sign">util-linux-2.28.2.tar.sign</a>                         07-Sep-2016 12:06     819
+<a href="util-linux-2.28.2.tar.xz">util-linux-2.28.2.tar.xz</a>                           07-Sep-2016 12:06      4M
+<a href="util-linux-2.28.tar.gz">util-linux-2.28.tar.gz</a>                             12-Apr-2016 11:26      8M
+<a href="util-linux-2.28.tar.sign">util-linux-2.28.tar.sign</a>                           12-Apr-2016 11:26     819
+<a href="util-linux-2.28.tar.xz">util-linux-2.28.tar.xz</a>                             12-Apr-2016 11:26      4M
+<a href="v2.28-ChangeLog">v2.28-ChangeLog</a>                                    12-Apr-2016 11:26     13K
+<a href="v2.28-ChangeLog.sign">v2.28-ChangeLog.sign</a>                               12-Apr-2016 11:26     819
+<a href="v2.28-ReleaseNotes">v2.28-ReleaseNotes</a>                                 12-Apr-2016 11:26     33K
+<a href="v2.28-ReleaseNotes.sign">v2.28-ReleaseNotes.sign</a>                            12-Apr-2016 11:26     819
+<a href="v2.28-rc1-ChangeLog">v2.28-rc1-ChangeLog</a>                                11-Mar-2016 11:45    269K
+<a href="v2.28-rc1-ChangeLog.sign">v2.28-rc1-ChangeLog.sign</a>                           11-Mar-2016 11:45     819
+<a href="v2.28-rc2-ChangeLog">v2.28-rc2-ChangeLog</a>                                29-Mar-2016 09:04     52K
+<a href="v2.28-rc2-ChangeLog.sign">v2.28-rc2-ChangeLog.sign</a>                           29-Mar-2016 09:04     819
+<a href="v2.28.1-ChangeLog">v2.28.1-ChangeLog</a>                                  11-Aug-2016 10:09     37K
+<a href="v2.28.1-ChangeLog.sign">v2.28.1-ChangeLog.sign</a>                             11-Aug-2016 10:09     819
+<a href="v2.28.1-ReleaseNotes">v2.28.1-ReleaseNotes</a>                               11-Aug-2016 10:09    3748
+<a href="v2.28.1-ReleaseNotes.sign">v2.28.1-ReleaseNotes.sign</a>                          11-Aug-2016 10:09     819
+<a href="v2.28.2-ChangeLog">v2.28.2-ChangeLog</a>                                  07-Sep-2016 12:06    8900
+<a href="v2.28.2-ChangeLog.sign">v2.28.2-ChangeLog.sign</a>                             07-Sep-2016 12:06     819
+<a href="v2.28.2-ReleaseNotes">v2.28.2-ReleaseNotes</a>                               07-Sep-2016 12:06    1161
+<a href="v2.28.2-ReleaseNotes.sign">v2.28.2-ReleaseNotes.sign</a>                          07-Sep-2016 12:06     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.29/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.29/index.html
index 07a8e51c..916a255f 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.29/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.29/index.html
@@ -1,42 +1,42 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.29/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.29/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     22-Feb-2017 15:20       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     22-Feb-2017 15:22       -
-<a href="libmount-docs/">libmount-docs/</a>                                     22-Feb-2017 15:24       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 22-Feb-2017 15:26       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:55    2480
-<a href="util-linux-2.29-rc1.tar.gz">util-linux-2.29-rc1.tar.gz</a>                         30-Sep-2016 09:55      9M
-<a href="util-linux-2.29-rc1.tar.sign">util-linux-2.29-rc1.tar.sign</a>                       30-Sep-2016 09:55     819
-<a href="util-linux-2.29-rc1.tar.xz">util-linux-2.29-rc1.tar.xz</a>                         30-Sep-2016 09:55      4M
-<a href="util-linux-2.29-rc2.tar.gz">util-linux-2.29-rc2.tar.gz</a>                         19-Oct-2016 13:13      9M
-<a href="util-linux-2.29-rc2.tar.sign">util-linux-2.29-rc2.tar.sign</a>                       19-Oct-2016 13:13     819
-<a href="util-linux-2.29-rc2.tar.xz">util-linux-2.29-rc2.tar.xz</a>                         19-Oct-2016 13:13      4M
-<a href="util-linux-2.29.1.tar.gz">util-linux-2.29.1.tar.gz</a>                           20-Jan-2017 14:02      9M
-<a href="util-linux-2.29.1.tar.sign">util-linux-2.29.1.tar.sign</a>                         20-Jan-2017 14:02     819
-<a href="util-linux-2.29.1.tar.xz">util-linux-2.29.1.tar.xz</a>                           20-Jan-2017 14:02      4M
-<a href="util-linux-2.29.2.tar.gz">util-linux-2.29.2.tar.gz</a>                           22-Feb-2017 15:26      9M
-<a href="util-linux-2.29.2.tar.sign">util-linux-2.29.2.tar.sign</a>                         22-Feb-2017 15:26     819
-<a href="util-linux-2.29.2.tar.xz">util-linux-2.29.2.tar.xz</a>                           22-Feb-2017 15:26      4M
-<a href="util-linux-2.29.tar.gz">util-linux-2.29.tar.gz</a>                             08-Nov-2016 11:23      9M
-<a href="util-linux-2.29.tar.sign">util-linux-2.29.tar.sign</a>                           08-Nov-2016 11:23     819
-<a href="util-linux-2.29.tar.xz">util-linux-2.29.tar.xz</a>                             08-Nov-2016 11:23      4M
-<a href="v2.29-ChangeLog">v2.29-ChangeLog</a>                                    08-Nov-2016 11:23     28K
-<a href="v2.29-ChangeLog.sign">v2.29-ChangeLog.sign</a>                               08-Nov-2016 11:23     819
-<a href="v2.29-ReleaseNotes">v2.29-ReleaseNotes</a>                                 08-Nov-2016 11:24     26K
-<a href="v2.29-ReleaseNotes.sign">v2.29-ReleaseNotes.sign</a>                            08-Nov-2016 11:24     819
-<a href="v2.29-rc1-ChangeLog">v2.29-rc1-ChangeLog</a>                                30-Sep-2016 09:55    219K
-<a href="v2.29-rc1-ChangeLog.sign">v2.29-rc1-ChangeLog.sign</a>                           30-Sep-2016 09:55     819
-<a href="v2.29-rc2-ChangeLog">v2.29-rc2-ChangeLog</a>                                19-Oct-2016 13:13     19K
-<a href="v2.29-rc2-ChangeLog.sign">v2.29-rc2-ChangeLog.sign</a>                           19-Oct-2016 13:13     819
-<a href="v2.29.1-ChangeLog">v2.29.1-ChangeLog</a>                                  20-Jan-2017 14:02     47K
-<a href="v2.29.1-ChangeLog.sign">v2.29.1-ChangeLog.sign</a>                             20-Jan-2017 14:02     819
-<a href="v2.29.1-ReleaseNotes">v2.29.1-ReleaseNotes</a>                               20-Jan-2017 14:02    5067
-<a href="v2.29.1-ReleaseNotes.sign">v2.29.1-ReleaseNotes.sign</a>                          20-Jan-2017 14:02     819
-<a href="v2.29.2-ChangeLog">v2.29.2-ChangeLog</a>                                  22-Feb-2017 15:26     14K
-<a href="v2.29.2-ChangeLog.sign">v2.29.2-ChangeLog.sign</a>                             22-Feb-2017 15:26     819
-<a href="v2.29.2-ReleaseNotes">v2.29.2-ReleaseNotes</a>                               22-Feb-2017 15:26    2012
-<a href="v2.29.2-ReleaseNotes.sign">v2.29.2-ReleaseNotes.sign</a>                          22-Feb-2017 15:26     819
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.29/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.29/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     22-Feb-2017 15:20       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     22-Feb-2017 15:22       -
+<a href="libmount-docs/">libmount-docs/</a>                                     22-Feb-2017 15:24       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 22-Feb-2017 15:26       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     12-May-2017 10:55    2480
+<a href="util-linux-2.29-rc1.tar.gz">util-linux-2.29-rc1.tar.gz</a>                         30-Sep-2016 09:55      9M
+<a href="util-linux-2.29-rc1.tar.sign">util-linux-2.29-rc1.tar.sign</a>                       30-Sep-2016 09:55     819
+<a href="util-linux-2.29-rc1.tar.xz">util-linux-2.29-rc1.tar.xz</a>                         30-Sep-2016 09:55      4M
+<a href="util-linux-2.29-rc2.tar.gz">util-linux-2.29-rc2.tar.gz</a>                         19-Oct-2016 13:13      9M
+<a href="util-linux-2.29-rc2.tar.sign">util-linux-2.29-rc2.tar.sign</a>                       19-Oct-2016 13:13     819
+<a href="util-linux-2.29-rc2.tar.xz">util-linux-2.29-rc2.tar.xz</a>                         19-Oct-2016 13:13      4M
+<a href="util-linux-2.29.1.tar.gz">util-linux-2.29.1.tar.gz</a>                           20-Jan-2017 14:02      9M
+<a href="util-linux-2.29.1.tar.sign">util-linux-2.29.1.tar.sign</a>                         20-Jan-2017 14:02     819
+<a href="util-linux-2.29.1.tar.xz">util-linux-2.29.1.tar.xz</a>                           20-Jan-2017 14:02      4M
+<a href="util-linux-2.29.2.tar.gz">util-linux-2.29.2.tar.gz</a>                           22-Feb-2017 15:26      9M
+<a href="util-linux-2.29.2.tar.sign">util-linux-2.29.2.tar.sign</a>                         22-Feb-2017 15:26     819
+<a href="util-linux-2.29.2.tar.xz">util-linux-2.29.2.tar.xz</a>                           22-Feb-2017 15:26      4M
+<a href="util-linux-2.29.tar.gz">util-linux-2.29.tar.gz</a>                             08-Nov-2016 11:23      9M
+<a href="util-linux-2.29.tar.sign">util-linux-2.29.tar.sign</a>                           08-Nov-2016 11:23     819
+<a href="util-linux-2.29.tar.xz">util-linux-2.29.tar.xz</a>                             08-Nov-2016 11:23      4M
+<a href="v2.29-ChangeLog">v2.29-ChangeLog</a>                                    08-Nov-2016 11:23     28K
+<a href="v2.29-ChangeLog.sign">v2.29-ChangeLog.sign</a>                               08-Nov-2016 11:23     819
+<a href="v2.29-ReleaseNotes">v2.29-ReleaseNotes</a>                                 08-Nov-2016 11:24     26K
+<a href="v2.29-ReleaseNotes.sign">v2.29-ReleaseNotes.sign</a>                            08-Nov-2016 11:24     819
+<a href="v2.29-rc1-ChangeLog">v2.29-rc1-ChangeLog</a>                                30-Sep-2016 09:55    219K
+<a href="v2.29-rc1-ChangeLog.sign">v2.29-rc1-ChangeLog.sign</a>                           30-Sep-2016 09:55     819
+<a href="v2.29-rc2-ChangeLog">v2.29-rc2-ChangeLog</a>                                19-Oct-2016 13:13     19K
+<a href="v2.29-rc2-ChangeLog.sign">v2.29-rc2-ChangeLog.sign</a>                           19-Oct-2016 13:13     819
+<a href="v2.29.1-ChangeLog">v2.29.1-ChangeLog</a>                                  20-Jan-2017 14:02     47K
+<a href="v2.29.1-ChangeLog.sign">v2.29.1-ChangeLog.sign</a>                             20-Jan-2017 14:02     819
+<a href="v2.29.1-ReleaseNotes">v2.29.1-ReleaseNotes</a>                               20-Jan-2017 14:02    5067
+<a href="v2.29.1-ReleaseNotes.sign">v2.29.1-ReleaseNotes.sign</a>                          20-Jan-2017 14:02     819
+<a href="v2.29.2-ChangeLog">v2.29.2-ChangeLog</a>                                  22-Feb-2017 15:26     14K
+<a href="v2.29.2-ChangeLog.sign">v2.29.2-ChangeLog.sign</a>                             22-Feb-2017 15:26     819
+<a href="v2.29.2-ReleaseNotes">v2.29.2-ReleaseNotes</a>                               22-Feb-2017 15:26    2012
+<a href="v2.29.2-ReleaseNotes.sign">v2.29.2-ReleaseNotes.sign</a>                          22-Feb-2017 15:26     819
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.30/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.30/index.html
index 6f17f06e..0441bc0d 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.30/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.30/index.html
@@ -1,42 +1,42 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.30/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.30/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     21-Sep-2017 09:49       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     21-Sep-2017 09:50       -
-<a href="libmount-docs/">libmount-docs/</a>                                     21-Sep-2017 09:50       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 21-Sep-2017 09:51       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     21-Sep-2017 09:52    2480
-<a href="util-linux-2.30-rc1.tar.gz">util-linux-2.30-rc1.tar.gz</a>                         12-May-2017 12:02      9M
-<a href="util-linux-2.30-rc1.tar.sign">util-linux-2.30-rc1.tar.sign</a>                       12-May-2017 12:02     819
-<a href="util-linux-2.30-rc1.tar.xz">util-linux-2.30-rc1.tar.xz</a>                         12-May-2017 12:02      4M
-<a href="util-linux-2.30-rc2.tar.gz">util-linux-2.30-rc2.tar.gz</a>                         23-May-2017 10:42      9M
-<a href="util-linux-2.30-rc2.tar.sign">util-linux-2.30-rc2.tar.sign</a>                       23-May-2017 10:42     819
-<a href="util-linux-2.30-rc2.tar.xz">util-linux-2.30-rc2.tar.xz</a>                         23-May-2017 10:42      4M
-<a href="util-linux-2.30.1.tar.gz">util-linux-2.30.1.tar.gz</a>                           20-Jul-2017 09:33      9M
-<a href="util-linux-2.30.1.tar.sign">util-linux-2.30.1.tar.sign</a>                         20-Jul-2017 09:33     819
-<a href="util-linux-2.30.1.tar.xz">util-linux-2.30.1.tar.xz</a>                           20-Jul-2017 09:33      4M
-<a href="util-linux-2.30.2.tar.gz">util-linux-2.30.2.tar.gz</a>                           21-Sep-2017 09:51      9M
-<a href="util-linux-2.30.2.tar.sign">util-linux-2.30.2.tar.sign</a>                         21-Sep-2017 09:51     833
-<a href="util-linux-2.30.2.tar.xz">util-linux-2.30.2.tar.xz</a>                           21-Sep-2017 09:51      4M
-<a href="util-linux-2.30.tar.gz">util-linux-2.30.tar.gz</a>                             02-Jun-2017 10:44      9M
-<a href="util-linux-2.30.tar.sign">util-linux-2.30.tar.sign</a>                           02-Jun-2017 10:44     819
-<a href="util-linux-2.30.tar.xz">util-linux-2.30.tar.xz</a>                             02-Jun-2017 10:44      4M
-<a href="v2.30-ChangeLog">v2.30-ChangeLog</a>                                    02-Jun-2017 10:44     28K
-<a href="v2.30-ChangeLog.sign">v2.30-ChangeLog.sign</a>                               02-Jun-2017 10:44     819
-<a href="v2.30-ReleaseNotes">v2.30-ReleaseNotes</a>                                 02-Jun-2017 10:44     34K
-<a href="v2.30-ReleaseNotes.sign">v2.30-ReleaseNotes.sign</a>                            02-Jun-2017 10:44     819
-<a href="v2.30-rc1-ChangeLog">v2.30-rc1-ChangeLog</a>                                23-May-2017 10:42    318K
-<a href="v2.30-rc1-ChangeLog.sign">v2.30-rc1-ChangeLog.sign</a>                           23-May-2017 10:42     819
-<a href="v2.30-rc2-ChangeLog">v2.30-rc2-ChangeLog</a>                                23-May-2017 10:42     19K
-<a href="v2.30-rc2-ChangeLog.sign">v2.30-rc2-ChangeLog.sign</a>                           23-May-2017 10:42     819
-<a href="v2.30.1-ChangeLog">v2.30.1-ChangeLog</a>                                  20-Jul-2017 09:33     20K
-<a href="v2.30.1-ChangeLog.sign">v2.30.1-ChangeLog.sign</a>                             20-Jul-2017 09:33     819
-<a href="v2.30.1-ReleaseNotes">v2.30.1-ReleaseNotes</a>                               20-Jul-2017 09:33    1901
-<a href="v2.30.1-ReleaseNotes.sign">v2.30.1-ReleaseNotes.sign</a>                          20-Jul-2017 09:33     819
-<a href="v2.30.2-ChangeLog">v2.30.2-ChangeLog</a>                                  21-Sep-2017 09:51     13K
-<a href="v2.30.2-ChangeLog.sign">v2.30.2-ChangeLog.sign</a>                             21-Sep-2017 09:51     833
-<a href="v2.30.2-ReleaseNotes">v2.30.2-ReleaseNotes</a>                               21-Sep-2017 09:51    1604
-<a href="v2.30.2-ReleaseNotes.sign">v2.30.2-ReleaseNotes.sign</a>                          21-Sep-2017 09:51     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.30/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.30/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     21-Sep-2017 09:49       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     21-Sep-2017 09:50       -
+<a href="libmount-docs/">libmount-docs/</a>                                     21-Sep-2017 09:50       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 21-Sep-2017 09:51       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     21-Sep-2017 09:52    2480
+<a href="util-linux-2.30-rc1.tar.gz">util-linux-2.30-rc1.tar.gz</a>                         12-May-2017 12:02      9M
+<a href="util-linux-2.30-rc1.tar.sign">util-linux-2.30-rc1.tar.sign</a>                       12-May-2017 12:02     819
+<a href="util-linux-2.30-rc1.tar.xz">util-linux-2.30-rc1.tar.xz</a>                         12-May-2017 12:02      4M
+<a href="util-linux-2.30-rc2.tar.gz">util-linux-2.30-rc2.tar.gz</a>                         23-May-2017 10:42      9M
+<a href="util-linux-2.30-rc2.tar.sign">util-linux-2.30-rc2.tar.sign</a>                       23-May-2017 10:42     819
+<a href="util-linux-2.30-rc2.tar.xz">util-linux-2.30-rc2.tar.xz</a>                         23-May-2017 10:42      4M
+<a href="util-linux-2.30.1.tar.gz">util-linux-2.30.1.tar.gz</a>                           20-Jul-2017 09:33      9M
+<a href="util-linux-2.30.1.tar.sign">util-linux-2.30.1.tar.sign</a>                         20-Jul-2017 09:33     819
+<a href="util-linux-2.30.1.tar.xz">util-linux-2.30.1.tar.xz</a>                           20-Jul-2017 09:33      4M
+<a href="util-linux-2.30.2.tar.gz">util-linux-2.30.2.tar.gz</a>                           21-Sep-2017 09:51      9M
+<a href="util-linux-2.30.2.tar.sign">util-linux-2.30.2.tar.sign</a>                         21-Sep-2017 09:51     833
+<a href="util-linux-2.30.2.tar.xz">util-linux-2.30.2.tar.xz</a>                           21-Sep-2017 09:51      4M
+<a href="util-linux-2.30.tar.gz">util-linux-2.30.tar.gz</a>                             02-Jun-2017 10:44      9M
+<a href="util-linux-2.30.tar.sign">util-linux-2.30.tar.sign</a>                           02-Jun-2017 10:44     819
+<a href="util-linux-2.30.tar.xz">util-linux-2.30.tar.xz</a>                             02-Jun-2017 10:44      4M
+<a href="v2.30-ChangeLog">v2.30-ChangeLog</a>                                    02-Jun-2017 10:44     28K
+<a href="v2.30-ChangeLog.sign">v2.30-ChangeLog.sign</a>                               02-Jun-2017 10:44     819
+<a href="v2.30-ReleaseNotes">v2.30-ReleaseNotes</a>                                 02-Jun-2017 10:44     34K
+<a href="v2.30-ReleaseNotes.sign">v2.30-ReleaseNotes.sign</a>                            02-Jun-2017 10:44     819
+<a href="v2.30-rc1-ChangeLog">v2.30-rc1-ChangeLog</a>                                23-May-2017 10:42    318K
+<a href="v2.30-rc1-ChangeLog.sign">v2.30-rc1-ChangeLog.sign</a>                           23-May-2017 10:42     819
+<a href="v2.30-rc2-ChangeLog">v2.30-rc2-ChangeLog</a>                                23-May-2017 10:42     19K
+<a href="v2.30-rc2-ChangeLog.sign">v2.30-rc2-ChangeLog.sign</a>                           23-May-2017 10:42     819
+<a href="v2.30.1-ChangeLog">v2.30.1-ChangeLog</a>                                  20-Jul-2017 09:33     20K
+<a href="v2.30.1-ChangeLog.sign">v2.30.1-ChangeLog.sign</a>                             20-Jul-2017 09:33     819
+<a href="v2.30.1-ReleaseNotes">v2.30.1-ReleaseNotes</a>                               20-Jul-2017 09:33    1901
+<a href="v2.30.1-ReleaseNotes.sign">v2.30.1-ReleaseNotes.sign</a>                          20-Jul-2017 09:33     819
+<a href="v2.30.2-ChangeLog">v2.30.2-ChangeLog</a>                                  21-Sep-2017 09:51     13K
+<a href="v2.30.2-ChangeLog.sign">v2.30.2-ChangeLog.sign</a>                             21-Sep-2017 09:51     833
+<a href="v2.30.2-ReleaseNotes">v2.30.2-ReleaseNotes</a>                               21-Sep-2017 09:51    1604
+<a href="v2.30.2-ReleaseNotes.sign">v2.30.2-ReleaseNotes.sign</a>                          21-Sep-2017 09:51     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.31/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.31/index.html
index e3c7dd5c..097e4e0e 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.31/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.31/index.html
@@ -1,35 +1,35 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.31/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.31/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     19-Dec-2017 15:16       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     19-Dec-2017 15:17       -
-<a href="libmount-docs/">libmount-docs/</a>                                     19-Dec-2017 15:17       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 19-Dec-2017 15:17       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     19-Dec-2017 15:20    2127
-<a href="util-linux-2.31-rc1.tar.gz">util-linux-2.31-rc1.tar.gz</a>                         22-Sep-2017 10:39      9M
-<a href="util-linux-2.31-rc1.tar.sign">util-linux-2.31-rc1.tar.sign</a>                       22-Sep-2017 10:39     833
-<a href="util-linux-2.31-rc1.tar.xz">util-linux-2.31-rc1.tar.xz</a>                         22-Sep-2017 10:39      4M
-<a href="util-linux-2.31-rc2.tar.gz">util-linux-2.31-rc2.tar.gz</a>                         03-Oct-2017 16:03      9M
-<a href="util-linux-2.31-rc2.tar.sign">util-linux-2.31-rc2.tar.sign</a>                       03-Oct-2017 16:03     833
-<a href="util-linux-2.31-rc2.tar.xz">util-linux-2.31-rc2.tar.xz</a>                         03-Oct-2017 16:03      4M
-<a href="util-linux-2.31.1.tar.gz">util-linux-2.31.1.tar.gz</a>                           19-Dec-2017 15:18      9M
-<a href="util-linux-2.31.1.tar.sign">util-linux-2.31.1.tar.sign</a>                         19-Dec-2017 15:18     833
-<a href="util-linux-2.31.1.tar.xz">util-linux-2.31.1.tar.xz</a>                           19-Dec-2017 15:18      4M
-<a href="util-linux-2.31.tar.gz">util-linux-2.31.tar.gz</a>                             19-Oct-2017 11:27      9M
-<a href="util-linux-2.31.tar.sign">util-linux-2.31.tar.sign</a>                           19-Oct-2017 11:27     833
-<a href="util-linux-2.31.tar.xz">util-linux-2.31.tar.xz</a>                             19-Oct-2017 11:27      4M
-<a href="v2.31-ChangeLog">v2.31-ChangeLog</a>                                    19-Oct-2017 11:27     15K
-<a href="v2.31-ChangeLog.sign">v2.31-ChangeLog.sign</a>                               19-Oct-2017 11:27     833
-<a href="v2.31-ReleaseNotes">v2.31-ReleaseNotes</a>                                 19-Oct-2017 11:27     31K
-<a href="v2.31-ReleaseNotes.sign">v2.31-ReleaseNotes.sign</a>                            19-Oct-2017 11:27     833
-<a href="v2.31-rc1-ChangeLog">v2.31-rc1-ChangeLog</a>                                22-Sep-2017 10:39    290K
-<a href="v2.31-rc1-ChangeLog.sign">v2.31-rc1-ChangeLog.sign</a>                           22-Sep-2017 10:39     833
-<a href="v2.31-rc2-ChangeLog">v2.31-rc2-ChangeLog</a>                                03-Oct-2017 16:03     12K
-<a href="v2.31-rc2-ChangeLog.sign">v2.31-rc2-ChangeLog.sign</a>                           03-Oct-2017 16:03     833
-<a href="v2.31.1-ChangeLog">v2.31.1-ChangeLog</a>                                  19-Dec-2017 15:18     27K
-<a href="v2.31.1-ChangeLog.sign">v2.31.1-ChangeLog.sign</a>                             19-Dec-2017 15:18     833
-<a href="v2.31.1-ReleaseNotes">v2.31.1-ReleaseNotes</a>                               19-Dec-2017 15:18    3175
-<a href="v2.31.1-ReleaseNotes.sign">v2.31.1-ReleaseNotes.sign</a>                          19-Dec-2017 15:18     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.31/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.31/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     19-Dec-2017 15:16       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     19-Dec-2017 15:17       -
+<a href="libmount-docs/">libmount-docs/</a>                                     19-Dec-2017 15:17       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 19-Dec-2017 15:17       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     19-Dec-2017 15:20    2127
+<a href="util-linux-2.31-rc1.tar.gz">util-linux-2.31-rc1.tar.gz</a>                         22-Sep-2017 10:39      9M
+<a href="util-linux-2.31-rc1.tar.sign">util-linux-2.31-rc1.tar.sign</a>                       22-Sep-2017 10:39     833
+<a href="util-linux-2.31-rc1.tar.xz">util-linux-2.31-rc1.tar.xz</a>                         22-Sep-2017 10:39      4M
+<a href="util-linux-2.31-rc2.tar.gz">util-linux-2.31-rc2.tar.gz</a>                         03-Oct-2017 16:03      9M
+<a href="util-linux-2.31-rc2.tar.sign">util-linux-2.31-rc2.tar.sign</a>                       03-Oct-2017 16:03     833
+<a href="util-linux-2.31-rc2.tar.xz">util-linux-2.31-rc2.tar.xz</a>                         03-Oct-2017 16:03      4M
+<a href="util-linux-2.31.1.tar.gz">util-linux-2.31.1.tar.gz</a>                           19-Dec-2017 15:18      9M
+<a href="util-linux-2.31.1.tar.sign">util-linux-2.31.1.tar.sign</a>                         19-Dec-2017 15:18     833
+<a href="util-linux-2.31.1.tar.xz">util-linux-2.31.1.tar.xz</a>                           19-Dec-2017 15:18      4M
+<a href="util-linux-2.31.tar.gz">util-linux-2.31.tar.gz</a>                             19-Oct-2017 11:27      9M
+<a href="util-linux-2.31.tar.sign">util-linux-2.31.tar.sign</a>                           19-Oct-2017 11:27     833
+<a href="util-linux-2.31.tar.xz">util-linux-2.31.tar.xz</a>                             19-Oct-2017 11:27      4M
+<a href="v2.31-ChangeLog">v2.31-ChangeLog</a>                                    19-Oct-2017 11:27     15K
+<a href="v2.31-ChangeLog.sign">v2.31-ChangeLog.sign</a>                               19-Oct-2017 11:27     833
+<a href="v2.31-ReleaseNotes">v2.31-ReleaseNotes</a>                                 19-Oct-2017 11:27     31K
+<a href="v2.31-ReleaseNotes.sign">v2.31-ReleaseNotes.sign</a>                            19-Oct-2017 11:27     833
+<a href="v2.31-rc1-ChangeLog">v2.31-rc1-ChangeLog</a>                                22-Sep-2017 10:39    290K
+<a href="v2.31-rc1-ChangeLog.sign">v2.31-rc1-ChangeLog.sign</a>                           22-Sep-2017 10:39     833
+<a href="v2.31-rc2-ChangeLog">v2.31-rc2-ChangeLog</a>                                03-Oct-2017 16:03     12K
+<a href="v2.31-rc2-ChangeLog.sign">v2.31-rc2-ChangeLog.sign</a>                           03-Oct-2017 16:03     833
+<a href="v2.31.1-ChangeLog">v2.31.1-ChangeLog</a>                                  19-Dec-2017 15:18     27K
+<a href="v2.31.1-ChangeLog.sign">v2.31.1-ChangeLog.sign</a>                             19-Dec-2017 15:18     833
+<a href="v2.31.1-ReleaseNotes">v2.31.1-ReleaseNotes</a>                               19-Dec-2017 15:18    3175
+<a href="v2.31.1-ReleaseNotes.sign">v2.31.1-ReleaseNotes.sign</a>                          19-Dec-2017 15:18     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.32/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.32/index.html
index 2955ace0..d373e981 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.32/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.32/index.html
@@ -1,35 +1,35 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.32/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.32/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     16-Jul-2018 11:27       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     16-Jul-2018 11:28       -
-<a href="libmount-docs/">libmount-docs/</a>                                     16-Jul-2018 11:28       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 16-Jul-2018 11:28       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     16-Jul-2018 11:30    2127
-<a href="util-linux-2.32-rc1.tar.gz">util-linux-2.32-rc1.tar.gz</a>                         13-Feb-2018 12:25      9M
-<a href="util-linux-2.32-rc1.tar.sign">util-linux-2.32-rc1.tar.sign</a>                       13-Feb-2018 12:25     833
-<a href="util-linux-2.32-rc1.tar.xz">util-linux-2.32-rc1.tar.xz</a>                         13-Feb-2018 12:25      4M
-<a href="util-linux-2.32-rc2.tar.gz">util-linux-2.32-rc2.tar.gz</a>                         01-Mar-2018 13:38      9M
-<a href="util-linux-2.32-rc2.tar.sign">util-linux-2.32-rc2.tar.sign</a>                       01-Mar-2018 13:38     833
-<a href="util-linux-2.32-rc2.tar.xz">util-linux-2.32-rc2.tar.xz</a>                         01-Mar-2018 13:38      4M
-<a href="util-linux-2.32.1.tar.gz">util-linux-2.32.1.tar.gz</a>                           16-Jul-2018 11:29      9M
-<a href="util-linux-2.32.1.tar.sign">util-linux-2.32.1.tar.sign</a>                         16-Jul-2018 11:29     833
-<a href="util-linux-2.32.1.tar.xz">util-linux-2.32.1.tar.xz</a>                           16-Jul-2018 11:29      4M
-<a href="util-linux-2.32.tar.gz">util-linux-2.32.tar.gz</a>                             21-Mar-2018 14:49      9M
-<a href="util-linux-2.32.tar.sign">util-linux-2.32.tar.sign</a>                           21-Mar-2018 14:49     833
-<a href="util-linux-2.32.tar.xz">util-linux-2.32.tar.xz</a>                             21-Mar-2018 14:49      4M
-<a href="v2.32-ChangeLog">v2.32-ChangeLog</a>                                    21-Mar-2018 14:49     36K
-<a href="v2.32-ChangeLog.sign">v2.32-ChangeLog.sign</a>                               21-Mar-2018 14:49     833
-<a href="v2.32-ReleaseNotes">v2.32-ReleaseNotes</a>                                 21-Mar-2018 14:49     21K
-<a href="v2.32-ReleaseNotes.sign">v2.32-ReleaseNotes.sign</a>                            21-Mar-2018 14:49     833
-<a href="v2.32-rc1-ChangeLog">v2.32-rc1-ChangeLog</a>                                13-Feb-2018 12:25    174K
-<a href="v2.32-rc1-ChangeLog.sign">v2.32-rc1-ChangeLog.sign</a>                           13-Feb-2018 12:25     833
-<a href="v2.32-rc2-ChangeLog">v2.32-rc2-ChangeLog</a>                                01-Mar-2018 13:38     21K
-<a href="v2.32-rc2-ChangeLog.sign">v2.32-rc2-ChangeLog.sign</a>                           01-Mar-2018 13:38     833
-<a href="v2.32.1-ChangeLog">v2.32.1-ChangeLog</a>                                  16-Jul-2018 11:29     31K
-<a href="v2.32.1-ChangeLog.sign">v2.32.1-ChangeLog.sign</a>                             16-Jul-2018 11:29     833
-<a href="v2.32.1-ReleaseNotes">v2.32.1-ReleaseNotes</a>                               16-Jul-2018 11:29    3425
-<a href="v2.32.1-ReleaseNotes.sign">v2.32.1-ReleaseNotes.sign</a>                          16-Jul-2018 11:29     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.32/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.32/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     16-Jul-2018 11:27       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     16-Jul-2018 11:28       -
+<a href="libmount-docs/">libmount-docs/</a>                                     16-Jul-2018 11:28       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 16-Jul-2018 11:28       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     16-Jul-2018 11:30    2127
+<a href="util-linux-2.32-rc1.tar.gz">util-linux-2.32-rc1.tar.gz</a>                         13-Feb-2018 12:25      9M
+<a href="util-linux-2.32-rc1.tar.sign">util-linux-2.32-rc1.tar.sign</a>                       13-Feb-2018 12:25     833
+<a href="util-linux-2.32-rc1.tar.xz">util-linux-2.32-rc1.tar.xz</a>                         13-Feb-2018 12:25      4M
+<a href="util-linux-2.32-rc2.tar.gz">util-linux-2.32-rc2.tar.gz</a>                         01-Mar-2018 13:38      9M
+<a href="util-linux-2.32-rc2.tar.sign">util-linux-2.32-rc2.tar.sign</a>                       01-Mar-2018 13:38     833
+<a href="util-linux-2.32-rc2.tar.xz">util-linux-2.32-rc2.tar.xz</a>                         01-Mar-2018 13:38      4M
+<a href="util-linux-2.32.1.tar.gz">util-linux-2.32.1.tar.gz</a>                           16-Jul-2018 11:29      9M
+<a href="util-linux-2.32.1.tar.sign">util-linux-2.32.1.tar.sign</a>                         16-Jul-2018 11:29     833
+<a href="util-linux-2.32.1.tar.xz">util-linux-2.32.1.tar.xz</a>                           16-Jul-2018 11:29      4M
+<a href="util-linux-2.32.tar.gz">util-linux-2.32.tar.gz</a>                             21-Mar-2018 14:49      9M
+<a href="util-linux-2.32.tar.sign">util-linux-2.32.tar.sign</a>                           21-Mar-2018 14:49     833
+<a href="util-linux-2.32.tar.xz">util-linux-2.32.tar.xz</a>                             21-Mar-2018 14:49      4M
+<a href="v2.32-ChangeLog">v2.32-ChangeLog</a>                                    21-Mar-2018 14:49     36K
+<a href="v2.32-ChangeLog.sign">v2.32-ChangeLog.sign</a>                               21-Mar-2018 14:49     833
+<a href="v2.32-ReleaseNotes">v2.32-ReleaseNotes</a>                                 21-Mar-2018 14:49     21K
+<a href="v2.32-ReleaseNotes.sign">v2.32-ReleaseNotes.sign</a>                            21-Mar-2018 14:49     833
+<a href="v2.32-rc1-ChangeLog">v2.32-rc1-ChangeLog</a>                                13-Feb-2018 12:25    174K
+<a href="v2.32-rc1-ChangeLog.sign">v2.32-rc1-ChangeLog.sign</a>                           13-Feb-2018 12:25     833
+<a href="v2.32-rc2-ChangeLog">v2.32-rc2-ChangeLog</a>                                01-Mar-2018 13:38     21K
+<a href="v2.32-rc2-ChangeLog.sign">v2.32-rc2-ChangeLog.sign</a>                           01-Mar-2018 13:38     833
+<a href="v2.32.1-ChangeLog">v2.32.1-ChangeLog</a>                                  16-Jul-2018 11:29     31K
+<a href="v2.32.1-ChangeLog.sign">v2.32.1-ChangeLog.sign</a>                             16-Jul-2018 11:29     833
+<a href="v2.32.1-ReleaseNotes">v2.32.1-ReleaseNotes</a>                               16-Jul-2018 11:29    3425
+<a href="v2.32.1-ReleaseNotes.sign">v2.32.1-ReleaseNotes.sign</a>                          16-Jul-2018 11:29     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.33/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.33/index.html
index 2c051750..54953054 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.33/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.33/index.html
@@ -1,42 +1,42 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.33/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.33/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     09-Apr-2019 13:55       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     09-Apr-2019 13:56       -
-<a href="libmount-docs/">libmount-docs/</a>                                     09-Apr-2019 13:56       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 09-Apr-2019 13:56       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     09-Apr-2019 14:01    2480
-<a href="util-linux-2.33-rc1.tar.gz">util-linux-2.33-rc1.tar.gz</a>                         25-Sep-2018 10:34      9M
-<a href="util-linux-2.33-rc1.tar.sign">util-linux-2.33-rc1.tar.sign</a>                       25-Sep-2018 10:34     833
-<a href="util-linux-2.33-rc1.tar.xz">util-linux-2.33-rc1.tar.xz</a>                         25-Sep-2018 10:34      4M
-<a href="util-linux-2.33-rc2.tar.gz">util-linux-2.33-rc2.tar.gz</a>                         19-Oct-2018 11:44      9M
-<a href="util-linux-2.33-rc2.tar.sign">util-linux-2.33-rc2.tar.sign</a>                       19-Oct-2018 11:44     833
-<a href="util-linux-2.33-rc2.tar.xz">util-linux-2.33-rc2.tar.xz</a>                         19-Oct-2018 11:44      4M
-<a href="util-linux-2.33.1.tar.gz">util-linux-2.33.1.tar.gz</a>                           09-Jan-2019 10:28      9M
-<a href="util-linux-2.33.1.tar.sign">util-linux-2.33.1.tar.sign</a>                         09-Jan-2019 10:28     833
-<a href="util-linux-2.33.1.tar.xz">util-linux-2.33.1.tar.xz</a>                           09-Jan-2019 10:28      4M
-<a href="util-linux-2.33.2.tar.gz">util-linux-2.33.2.tar.gz</a>                           09-Apr-2019 13:57     10M
-<a href="util-linux-2.33.2.tar.sign">util-linux-2.33.2.tar.sign</a>                         09-Apr-2019 13:57     833
-<a href="util-linux-2.33.2.tar.xz">util-linux-2.33.2.tar.xz</a>                           09-Apr-2019 13:57      4M
-<a href="util-linux-2.33.tar.gz">util-linux-2.33.tar.gz</a>                             06-Nov-2018 11:25      9M
-<a href="util-linux-2.33.tar.sign">util-linux-2.33.tar.sign</a>                           06-Nov-2018 11:25     833
-<a href="util-linux-2.33.tar.xz">util-linux-2.33.tar.xz</a>                             06-Nov-2018 11:25      4M
-<a href="v2.33-ChangeLog">v2.33-ChangeLog</a>                                    06-Nov-2018 11:25    7977
-<a href="v2.33-ChangeLog.sign">v2.33-ChangeLog.sign</a>                               06-Nov-2018 11:25     833
-<a href="v2.33-ReleaseNotes">v2.33-ReleaseNotes</a>                                 06-Nov-2018 11:25     27K
-<a href="v2.33-ReleaseNotes.sign">v2.33-ReleaseNotes.sign</a>                            06-Nov-2018 11:25     833
-<a href="v2.33-rc1-ChangeLog">v2.33-rc1-ChangeLog</a>                                25-Sep-2018 10:34    210K
-<a href="v2.33-rc1-ChangeLog.sign">v2.33-rc1-ChangeLog.sign</a>                           25-Sep-2018 10:34     833
-<a href="v2.33-rc2-ChangeLog">v2.33-rc2-ChangeLog</a>                                19-Oct-2018 11:44     18K
-<a href="v2.33-rc2-ChangeLog.sign">v2.33-rc2-ChangeLog.sign</a>                           19-Oct-2018 11:44     833
-<a href="v2.33.1-ChangeLog">v2.33.1-ChangeLog</a>                                  09-Jan-2019 10:28     17K
-<a href="v2.33.1-ChangeLog.sign">v2.33.1-ChangeLog.sign</a>                             09-Jan-2019 10:28     833
-<a href="v2.33.1-ReleaseNotes">v2.33.1-ReleaseNotes</a>                               09-Jan-2019 10:28    1899
-<a href="v2.33.1-ReleaseNotes.sign">v2.33.1-ReleaseNotes.sign</a>                          09-Jan-2019 10:28     833
-<a href="v2.33.2-ChangeLog">v2.33.2-ChangeLog</a>                                  09-Apr-2019 13:57     21K
-<a href="v2.33.2-ChangeLog.sign">v2.33.2-ChangeLog.sign</a>                             09-Apr-2019 13:57     833
-<a href="v2.33.2-ReleaseNotes">v2.33.2-ReleaseNotes</a>                               09-Apr-2019 13:57    2566
-<a href="v2.33.2-ReleaseNotes.sign">v2.33.2-ReleaseNotes.sign</a>                          09-Apr-2019 13:57     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.33/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.33/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     09-Apr-2019 13:55       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     09-Apr-2019 13:56       -
+<a href="libmount-docs/">libmount-docs/</a>                                     09-Apr-2019 13:56       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 09-Apr-2019 13:56       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     09-Apr-2019 14:01    2480
+<a href="util-linux-2.33-rc1.tar.gz">util-linux-2.33-rc1.tar.gz</a>                         25-Sep-2018 10:34      9M
+<a href="util-linux-2.33-rc1.tar.sign">util-linux-2.33-rc1.tar.sign</a>                       25-Sep-2018 10:34     833
+<a href="util-linux-2.33-rc1.tar.xz">util-linux-2.33-rc1.tar.xz</a>                         25-Sep-2018 10:34      4M
+<a href="util-linux-2.33-rc2.tar.gz">util-linux-2.33-rc2.tar.gz</a>                         19-Oct-2018 11:44      9M
+<a href="util-linux-2.33-rc2.tar.sign">util-linux-2.33-rc2.tar.sign</a>                       19-Oct-2018 11:44     833
+<a href="util-linux-2.33-rc2.tar.xz">util-linux-2.33-rc2.tar.xz</a>                         19-Oct-2018 11:44      4M
+<a href="util-linux-2.33.1.tar.gz">util-linux-2.33.1.tar.gz</a>                           09-Jan-2019 10:28      9M
+<a href="util-linux-2.33.1.tar.sign">util-linux-2.33.1.tar.sign</a>                         09-Jan-2019 10:28     833
+<a href="util-linux-2.33.1.tar.xz">util-linux-2.33.1.tar.xz</a>                           09-Jan-2019 10:28      4M
+<a href="util-linux-2.33.2.tar.gz">util-linux-2.33.2.tar.gz</a>                           09-Apr-2019 13:57     10M
+<a href="util-linux-2.33.2.tar.sign">util-linux-2.33.2.tar.sign</a>                         09-Apr-2019 13:57     833
+<a href="util-linux-2.33.2.tar.xz">util-linux-2.33.2.tar.xz</a>                           09-Apr-2019 13:57      4M
+<a href="util-linux-2.33.tar.gz">util-linux-2.33.tar.gz</a>                             06-Nov-2018 11:25      9M
+<a href="util-linux-2.33.tar.sign">util-linux-2.33.tar.sign</a>                           06-Nov-2018 11:25     833
+<a href="util-linux-2.33.tar.xz">util-linux-2.33.tar.xz</a>                             06-Nov-2018 11:25      4M
+<a href="v2.33-ChangeLog">v2.33-ChangeLog</a>                                    06-Nov-2018 11:25    7977
+<a href="v2.33-ChangeLog.sign">v2.33-ChangeLog.sign</a>                               06-Nov-2018 11:25     833
+<a href="v2.33-ReleaseNotes">v2.33-ReleaseNotes</a>                                 06-Nov-2018 11:25     27K
+<a href="v2.33-ReleaseNotes.sign">v2.33-ReleaseNotes.sign</a>                            06-Nov-2018 11:25     833
+<a href="v2.33-rc1-ChangeLog">v2.33-rc1-ChangeLog</a>                                25-Sep-2018 10:34    210K
+<a href="v2.33-rc1-ChangeLog.sign">v2.33-rc1-ChangeLog.sign</a>                           25-Sep-2018 10:34     833
+<a href="v2.33-rc2-ChangeLog">v2.33-rc2-ChangeLog</a>                                19-Oct-2018 11:44     18K
+<a href="v2.33-rc2-ChangeLog.sign">v2.33-rc2-ChangeLog.sign</a>                           19-Oct-2018 11:44     833
+<a href="v2.33.1-ChangeLog">v2.33.1-ChangeLog</a>                                  09-Jan-2019 10:28     17K
+<a href="v2.33.1-ChangeLog.sign">v2.33.1-ChangeLog.sign</a>                             09-Jan-2019 10:28     833
+<a href="v2.33.1-ReleaseNotes">v2.33.1-ReleaseNotes</a>                               09-Jan-2019 10:28    1899
+<a href="v2.33.1-ReleaseNotes.sign">v2.33.1-ReleaseNotes.sign</a>                          09-Jan-2019 10:28     833
+<a href="v2.33.2-ChangeLog">v2.33.2-ChangeLog</a>                                  09-Apr-2019 13:57     21K
+<a href="v2.33.2-ChangeLog.sign">v2.33.2-ChangeLog.sign</a>                             09-Apr-2019 13:57     833
+<a href="v2.33.2-ReleaseNotes">v2.33.2-ReleaseNotes</a>                               09-Apr-2019 13:57    2566
+<a href="v2.33.2-ReleaseNotes.sign">v2.33.2-ReleaseNotes.sign</a>                          09-Apr-2019 13:57     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.34/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.34/index.html
index ac6c34f6..bd9d9c87 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.34/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.34/index.html
@@ -1,28 +1,28 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.34/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.34/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     14-Jun-2019 10:45       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     14-Jun-2019 10:45       -
-<a href="libmount-docs/">libmount-docs/</a>                                     14-Jun-2019 10:45       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 14-Jun-2019 10:46       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     14-Jun-2019 10:51    1774
-<a href="util-linux-2.34-rc1.tar.gz">util-linux-2.34-rc1.tar.gz</a>                         30-Apr-2019 10:24     10M
-<a href="util-linux-2.34-rc1.tar.sign">util-linux-2.34-rc1.tar.sign</a>                       30-Apr-2019 10:24     833
-<a href="util-linux-2.34-rc1.tar.xz">util-linux-2.34-rc1.tar.xz</a>                         30-Apr-2019 10:24      5M
-<a href="util-linux-2.34-rc2.tar.gz">util-linux-2.34-rc2.tar.gz</a>                         30-May-2019 10:24     10M
-<a href="util-linux-2.34-rc2.tar.sign">util-linux-2.34-rc2.tar.sign</a>                       30-May-2019 10:24     833
-<a href="util-linux-2.34-rc2.tar.xz">util-linux-2.34-rc2.tar.xz</a>                         30-May-2019 10:24      5M
-<a href="util-linux-2.34.tar.gz">util-linux-2.34.tar.gz</a>                             14-Jun-2019 10:46     10M
-<a href="util-linux-2.34.tar.sign">util-linux-2.34.tar.sign</a>                           14-Jun-2019 10:46     833
-<a href="util-linux-2.34.tar.xz">util-linux-2.34.tar.xz</a>                             14-Jun-2019 10:46      5M
-<a href="v2.34-ChangeLog">v2.34-ChangeLog</a>                                    14-Jun-2019 10:46     14K
-<a href="v2.34-ChangeLog.sign">v2.34-ChangeLog.sign</a>                               14-Jun-2019 10:46     833
-<a href="v2.34-ReleaseNotes">v2.34-ReleaseNotes</a>                                 14-Jun-2019 10:46     27K
-<a href="v2.34-ReleaseNotes.sign">v2.34-ReleaseNotes.sign</a>                            14-Jun-2019 10:46     833
-<a href="v2.34-rc1-ChangeLog">v2.34-rc1-ChangeLog</a>                                30-Apr-2019 10:24    167K
-<a href="v2.34-rc1-ChangeLog.sign">v2.34-rc1-ChangeLog.sign</a>                           30-Apr-2019 10:24     833
-<a href="v2.34-rc2-ChangeLog">v2.34-rc2-ChangeLog</a>                                30-May-2019 10:24     57K
-<a href="v2.34-rc2-ChangeLog.sign">v2.34-rc2-ChangeLog.sign</a>                           30-May-2019 10:24     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.34/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.34/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     14-Jun-2019 10:45       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     14-Jun-2019 10:45       -
+<a href="libmount-docs/">libmount-docs/</a>                                     14-Jun-2019 10:45       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 14-Jun-2019 10:46       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     14-Jun-2019 10:51    1774
+<a href="util-linux-2.34-rc1.tar.gz">util-linux-2.34-rc1.tar.gz</a>                         30-Apr-2019 10:24     10M
+<a href="util-linux-2.34-rc1.tar.sign">util-linux-2.34-rc1.tar.sign</a>                       30-Apr-2019 10:24     833
+<a href="util-linux-2.34-rc1.tar.xz">util-linux-2.34-rc1.tar.xz</a>                         30-Apr-2019 10:24      5M
+<a href="util-linux-2.34-rc2.tar.gz">util-linux-2.34-rc2.tar.gz</a>                         30-May-2019 10:24     10M
+<a href="util-linux-2.34-rc2.tar.sign">util-linux-2.34-rc2.tar.sign</a>                       30-May-2019 10:24     833
+<a href="util-linux-2.34-rc2.tar.xz">util-linux-2.34-rc2.tar.xz</a>                         30-May-2019 10:24      5M
+<a href="util-linux-2.34.tar.gz">util-linux-2.34.tar.gz</a>                             14-Jun-2019 10:46     10M
+<a href="util-linux-2.34.tar.sign">util-linux-2.34.tar.sign</a>                           14-Jun-2019 10:46     833
+<a href="util-linux-2.34.tar.xz">util-linux-2.34.tar.xz</a>                             14-Jun-2019 10:46      5M
+<a href="v2.34-ChangeLog">v2.34-ChangeLog</a>                                    14-Jun-2019 10:46     14K
+<a href="v2.34-ChangeLog.sign">v2.34-ChangeLog.sign</a>                               14-Jun-2019 10:46     833
+<a href="v2.34-ReleaseNotes">v2.34-ReleaseNotes</a>                                 14-Jun-2019 10:46     27K
+<a href="v2.34-ReleaseNotes.sign">v2.34-ReleaseNotes.sign</a>                            14-Jun-2019 10:46     833
+<a href="v2.34-rc1-ChangeLog">v2.34-rc1-ChangeLog</a>                                30-Apr-2019 10:24    167K
+<a href="v2.34-rc1-ChangeLog.sign">v2.34-rc1-ChangeLog.sign</a>                           30-Apr-2019 10:24     833
+<a href="v2.34-rc2-ChangeLog">v2.34-rc2-ChangeLog</a>                                30-May-2019 10:24     57K
+<a href="v2.34-rc2-ChangeLog.sign">v2.34-rc2-ChangeLog.sign</a>                           30-May-2019 10:24     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.35/index.html b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.35/index.html
index 66dc0c59..aa714d39 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.35/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/pub/linux/utils/util-linux/v2.35/index.html
@@ -1,18 +1,18 @@
-<html>
-<head><title>Index of /pub/linux/utils/util-linux/v2.35/</title></head>
-<body>
-<h1>Index of /pub/linux/utils/util-linux/v2.35/</h1><hr><pre><a href="../">../</a>
-<a href="libblkid-docs/">libblkid-docs/</a>                                     11-Dec-2019 10:04       -
-<a href="libfdisk-docs/">libfdisk-docs/</a>                                     11-Dec-2019 10:05       -
-<a href="libmount-docs/">libmount-docs/</a>                                     11-Dec-2019 10:05       -
-<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 11-Dec-2019 10:05       -
-<a href="sha256sums.asc">sha256sums.asc</a>                                     11-Dec-2019 10:11    1242
-<a href="util-linux-2.35-rc1.tar.gz">util-linux-2.35-rc1.tar.gz</a>                         11-Dec-2019 10:06     10M
-<a href="util-linux-2.35-rc1.tar.sign">util-linux-2.35-rc1.tar.sign</a>                       11-Dec-2019 10:06     833
-<a href="util-linux-2.35-rc1.tar.xz">util-linux-2.35-rc1.tar.xz</a>                         11-Dec-2019 10:06      5M
-<a href="v2.35-ReleaseNotes">v2.35-ReleaseNotes</a>                                 11-Dec-2019 10:06     21K
-<a href="v2.35-ReleaseNotes.sign">v2.35-ReleaseNotes.sign</a>                            11-Dec-2019 10:06     833
-<a href="v2.35-rc1-ChangeLog">v2.35-rc1-ChangeLog</a>                                11-Dec-2019 10:06    228K
-<a href="v2.35-rc1-ChangeLog.sign">v2.35-rc1-ChangeLog.sign</a>                           11-Dec-2019 10:06     833
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /pub/linux/utils/util-linux/v2.35/</title></head>
+<body>
+<h1>Index of /pub/linux/utils/util-linux/v2.35/</h1><hr><pre><a href="../">../</a>
+<a href="libblkid-docs/">libblkid-docs/</a>                                     11-Dec-2019 10:04       -
+<a href="libfdisk-docs/">libfdisk-docs/</a>                                     11-Dec-2019 10:05       -
+<a href="libmount-docs/">libmount-docs/</a>                                     11-Dec-2019 10:05       -
+<a href="libsmartcols-docs/">libsmartcols-docs/</a>                                 11-Dec-2019 10:05       -
+<a href="sha256sums.asc">sha256sums.asc</a>                                     11-Dec-2019 10:11    1242
+<a href="util-linux-2.35-rc1.tar.gz">util-linux-2.35-rc1.tar.gz</a>                         11-Dec-2019 10:06     10M
+<a href="util-linux-2.35-rc1.tar.sign">util-linux-2.35-rc1.tar.sign</a>                       11-Dec-2019 10:06     833
+<a href="util-linux-2.35-rc1.tar.xz">util-linux-2.35-rc1.tar.xz</a>                         11-Dec-2019 10:06      5M
+<a href="v2.35-ReleaseNotes">v2.35-ReleaseNotes</a>                                 11-Dec-2019 10:06     21K
+<a href="v2.35-ReleaseNotes.sign">v2.35-ReleaseNotes.sign</a>                            11-Dec-2019 10:06     833
+<a href="v2.35-rc1-ChangeLog">v2.35-rc1-ChangeLog</a>                                11-Dec-2019 10:06    228K
+<a href="v2.35-rc1-ChangeLog.sign">v2.35-rc1-ChangeLog.sign</a>                           11-Dec-2019 10:06     833
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/releases/eglibc/index.html b/bitbake/lib/bb/tests/fetch-testdata/releases/eglibc/index.html
index ca97c87f..b2679402 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/releases/eglibc/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/releases/eglibc/index.html
@@ -1,21 +1,21 @@
-<html>
-<head><title>Index of /releases/eglibc/</title></head>
-<body bgcolor="white">
-<h1>Index of /releases/eglibc/</h1><hr><pre><a href="../">../</a>
-<a href="eglibc-2.16-svnr21224.tar.bz2">eglibc-2.16-svnr21224.tar.bz2</a>                      17-Oct-2012 18:01            17310656
-<a href="eglibc-2.16-svnr21224.tar.bz2.md5">eglibc-2.16-svnr21224.tar.bz2.md5</a>                  17-Oct-2012 21:53                  64
-<a href="eglibc-2.16-svnr21224.tar.bz2.sha1">eglibc-2.16-svnr21224.tar.bz2.sha1</a>                 17-Oct-2012 21:53                  72
-<a href="eglibc-2.17-svnr22064.tar.bz2">eglibc-2.17-svnr22064.tar.bz2</a>                      04-Jan-2013 05:44            17565519
-<a href="eglibc-2.17-svnr22064.tar.bz2.asc">eglibc-2.17-svnr22064.tar.bz2.asc</a>                  04-Jan-2013 05:45                 302
-<a href="eglibc-2.17-svnr22064.tar.bz2.md5">eglibc-2.17-svnr22064.tar.bz2.md5</a>                  04-Jan-2013 05:44                  64
-<a href="eglibc-2.17-svnr22064.tar.bz2.sha1">eglibc-2.17-svnr22064.tar.bz2.sha1</a>                 04-Jan-2013 05:44                  72
-<a href="eglibc-2.18-svnr23787.tar.bz2">eglibc-2.18-svnr23787.tar.bz2</a>                      21-Aug-2013 05:36            17862773
-<a href="eglibc-2.18-svnr23787.tar.bz2.asc">eglibc-2.18-svnr23787.tar.bz2.asc</a>                  21-Aug-2013 05:36                 302
-<a href="eglibc-2.18-svnr23787.tar.bz2.md5">eglibc-2.18-svnr23787.tar.bz2.md5</a>                  21-Aug-2013 05:36                  64
-<a href="eglibc-2.18-svnr23787.tar.bz2.sha1">eglibc-2.18-svnr23787.tar.bz2.sha1</a>                 21-Aug-2013 05:36                  72
-<a href="eglibc-2.19-svnr25243.tar.bz2">eglibc-2.19-svnr25243.tar.bz2</a>                      08-Feb-2014 10:06            18873620
-<a href="eglibc-2.19-svnr25243.tar.bz2.asc">eglibc-2.19-svnr25243.tar.bz2.asc</a>                  08-Feb-2014 10:06                 285
-<a href="eglibc-2.19-svnr25243.tar.bz2.md5">eglibc-2.19-svnr25243.tar.bz2.md5</a>                  08-Feb-2014 10:06                  64
-<a href="eglibc-2.19-svnr25243.tar.bz2.sha1">eglibc-2.19-svnr25243.tar.bz2.sha1</a>                 08-Feb-2014 10:06                  72
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /releases/eglibc/</title></head>
+<body bgcolor="white">
+<h1>Index of /releases/eglibc/</h1><hr><pre><a href="../">../</a>
+<a href="eglibc-2.16-svnr21224.tar.bz2">eglibc-2.16-svnr21224.tar.bz2</a>                      17-Oct-2012 18:01            17310656
+<a href="eglibc-2.16-svnr21224.tar.bz2.md5">eglibc-2.16-svnr21224.tar.bz2.md5</a>                  17-Oct-2012 21:53                  64
+<a href="eglibc-2.16-svnr21224.tar.bz2.sha1">eglibc-2.16-svnr21224.tar.bz2.sha1</a>                 17-Oct-2012 21:53                  72
+<a href="eglibc-2.17-svnr22064.tar.bz2">eglibc-2.17-svnr22064.tar.bz2</a>                      04-Jan-2013 05:44            17565519
+<a href="eglibc-2.17-svnr22064.tar.bz2.asc">eglibc-2.17-svnr22064.tar.bz2.asc</a>                  04-Jan-2013 05:45                 302
+<a href="eglibc-2.17-svnr22064.tar.bz2.md5">eglibc-2.17-svnr22064.tar.bz2.md5</a>                  04-Jan-2013 05:44                  64
+<a href="eglibc-2.17-svnr22064.tar.bz2.sha1">eglibc-2.17-svnr22064.tar.bz2.sha1</a>                 04-Jan-2013 05:44                  72
+<a href="eglibc-2.18-svnr23787.tar.bz2">eglibc-2.18-svnr23787.tar.bz2</a>                      21-Aug-2013 05:36            17862773
+<a href="eglibc-2.18-svnr23787.tar.bz2.asc">eglibc-2.18-svnr23787.tar.bz2.asc</a>                  21-Aug-2013 05:36                 302
+<a href="eglibc-2.18-svnr23787.tar.bz2.md5">eglibc-2.18-svnr23787.tar.bz2.md5</a>                  21-Aug-2013 05:36                  64
+<a href="eglibc-2.18-svnr23787.tar.bz2.sha1">eglibc-2.18-svnr23787.tar.bz2.sha1</a>                 21-Aug-2013 05:36                  72
+<a href="eglibc-2.19-svnr25243.tar.bz2">eglibc-2.19-svnr25243.tar.bz2</a>                      08-Feb-2014 10:06            18873620
+<a href="eglibc-2.19-svnr25243.tar.bz2.asc">eglibc-2.19-svnr25243.tar.bz2.asc</a>                  08-Feb-2014 10:06                 285
+<a href="eglibc-2.19-svnr25243.tar.bz2.md5">eglibc-2.19-svnr25243.tar.bz2.md5</a>                  08-Feb-2014 10:06                  64
+<a href="eglibc-2.19-svnr25243.tar.bz2.sha1">eglibc-2.19-svnr25243.tar.bz2.sha1</a>                 08-Feb-2014 10:06                  72
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch-testdata/releases/gnu-config/index.html b/bitbake/lib/bb/tests/fetch-testdata/releases/gnu-config/index.html
index bf85a50b..051aa481 100644
--- a/bitbake/lib/bb/tests/fetch-testdata/releases/gnu-config/index.html
+++ b/bitbake/lib/bb/tests/fetch-testdata/releases/gnu-config/index.html
@@ -1,9 +1,9 @@
-<html>
-<head><title>Index of /releases/gnu-config/</title></head>
-<body bgcolor="white">
-<h1>Index of /releases/gnu-config/</h1><hr><pre><a href="../">../</a>
-<a href="SHA256SUM">SHA256SUM</a>                                          03-Oct-2012 17:23                 190
-<a href="gnu-config-20120814.tar.bz2">gnu-config-20120814.tar.bz2</a>                        18-Sep-2012 09:28               43026
-<a href="gnu-config-yocto-20111111.tgz">gnu-config-yocto-20111111.tgz</a>                      08-May-2012 21:11               48762
-</pre><hr></body>
-</html>
+<html>
+<head><title>Index of /releases/gnu-config/</title></head>
+<body bgcolor="white">
+<h1>Index of /releases/gnu-config/</h1><hr><pre><a href="../">../</a>
+<a href="SHA256SUM">SHA256SUM</a>                                          03-Oct-2012 17:23                 190
+<a href="gnu-config-20120814.tar.bz2">gnu-config-20120814.tar.bz2</a>                        18-Sep-2012 09:28               43026
+<a href="gnu-config-yocto-20111111.tgz">gnu-config-yocto-20111111.tgz</a>                      08-May-2012 21:11               48762
+</pre><hr></body>
+</html>
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py
index 29c96b2b..f5d557e8 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -87,6 +87,25 @@ class URITest(unittest.TestCase):
             },
             'relative': False
         },
+        # Check that trailing semicolons are handled correctly
+        "http://www.example.org/index.html?qparam1=qvalue1;param2=value2;" : {
+            'uri': 'http://www.example.org/index.html?qparam1=qvalue1;param2=value2',
+            'scheme': 'http',
+            'hostname': 'www.example.org',
+            'port': None,
+            'hostport': 'www.example.org',
+            'path': '/index.html',
+            'userinfo': '',
+            'username': '',
+            'password': '',
+            'params': {
+                'param2': 'value2'
+            },
+            'query': {
+                'qparam1': 'qvalue1'
+            },
+            'relative': False
+        },
         "http://www.example.com:8080/index.html" : {
             'uri': 'http://www.example.com:8080/index.html',
             'scheme': 'http',
@@ -223,6 +242,21 @@ class URITest(unittest.TestCase):
             'query': {},
             'relative': False
         },
+        "git://tfs-example.org:22/tfs/example%20path/example.git": {
+            'uri': 'git://tfs-example.org:22/tfs/example%20path/example.git',
+            'scheme': 'git',
+            'hostname': 'tfs-example.org',
+            'port': 22,
+            'hostport': 'tfs-example.org:22',
+            'path': '/tfs/example path/example.git',
+            'userinfo': '',
+            'userinfo': '',
+            'username': '',
+            'password': '',
+            'params': {},
+            'query': {},
+            'relative': False
+        },
         "http://somesite.net;someparam=1": {
             'uri': 'http://somesite.net;someparam=1',
             'scheme': 'http',
@@ -356,6 +390,7 @@ class FetcherTest(unittest.TestCase):
         if os.environ.get("BB_TMPDIR_NOCLEAN") == "yes":
             print("Not cleaning up %s. Please remove manually." % self.tempdir)
         else:
+            bb.process.run('chmod u+rw -R %s' % self.tempdir)
             bb.utils.prunedir(self.tempdir)
 
 class MirrorUriTest(FetcherTest):
@@ -584,6 +619,7 @@ class FetcherLocalTest(FetcherTest):
         touch(os.path.join(self.localsrcdir, 'dir', 'd'))
         os.makedirs(os.path.join(self.localsrcdir, 'dir', 'subdir'))
         touch(os.path.join(self.localsrcdir, 'dir', 'subdir', 'e'))
+        touch(os.path.join(self.localsrcdir, r'backslash\x2dsystemd-unit.device'))
         self.d.setVar("FILESPATH", self.localsrcdir)
 
     def fetchUnpack(self, uris):
@@ -601,9 +637,13 @@ class FetcherLocalTest(FetcherTest):
         tree = self.fetchUnpack(['file://a', 'file://dir/c'])
         self.assertEqual(tree, ['a', 'dir/c'])
 
+    def test_local_backslash(self):
+        tree = self.fetchUnpack([r'file://backslash\x2dsystemd-unit.device'])
+        self.assertEqual(tree, [r'backslash\x2dsystemd-unit.device'])
+
     def test_local_wildcard(self):
-        tree = self.fetchUnpack(['file://a', 'file://dir/*'])
-        self.assertEqual(tree, ['a',  'dir/c', 'dir/d', 'dir/subdir/e'])
+        with self.assertRaises(bb.fetch2.ParameterError):
+            tree = self.fetchUnpack(['file://a', 'file://dir/*'])
 
     def test_local_dir(self):
         tree = self.fetchUnpack(['file://a', 'file://dir'])
@@ -634,6 +674,62 @@ class FetcherLocalTest(FetcherTest):
         with self.assertRaises(bb.fetch2.UnpackError):
             self.fetchUnpack(['file://a;subdir=/bin/sh'])
 
+    def test_local_gitfetch_usehead(self):
+        # Create dummy local Git repo
+        src_dir = tempfile.mkdtemp(dir=self.tempdir,
+                                   prefix='gitfetch_localusehead_')
+        src_dir = os.path.abspath(src_dir)
+        bb.process.run("git init", cwd=src_dir)
+        bb.process.run("git config user.email 'you@example.com'", cwd=src_dir)
+        bb.process.run("git config user.name 'Your Name'", cwd=src_dir)
+        bb.process.run("git commit --allow-empty -m'Dummy commit'",
+                       cwd=src_dir)
+        # Use other branch than master
+        bb.process.run("git checkout -b my-devel", cwd=src_dir)
+        bb.process.run("git commit --allow-empty -m'Dummy commit 2'",
+                       cwd=src_dir)
+        stdout = bb.process.run("git rev-parse HEAD", cwd=src_dir)
+        orig_rev = stdout[0].strip()
+
+        # Fetch and check revision
+        self.d.setVar("SRCREV", "AUTOINC")
+        url = "git://" + src_dir + ";protocol=file;usehead=1"
+        fetcher = bb.fetch.Fetch([url], self.d)
+        fetcher.download()
+        fetcher.unpack(self.unpackdir)
+        stdout = bb.process.run("git rev-parse HEAD",
+                                cwd=os.path.join(self.unpackdir, 'git'))
+        unpack_rev = stdout[0].strip()
+        self.assertEqual(orig_rev, unpack_rev)
+
+    def test_local_gitfetch_usehead_withname(self):
+        # Create dummy local Git repo
+        src_dir = tempfile.mkdtemp(dir=self.tempdir,
+                                   prefix='gitfetch_localusehead_')
+        src_dir = os.path.abspath(src_dir)
+        bb.process.run("git init", cwd=src_dir)
+        bb.process.run("git config user.email 'you@example.com'", cwd=src_dir)
+        bb.process.run("git config user.name 'Your Name'", cwd=src_dir)
+        bb.process.run("git commit --allow-empty -m'Dummy commit'",
+                       cwd=src_dir)
+        # Use other branch than master
+        bb.process.run("git checkout -b my-devel", cwd=src_dir)
+        bb.process.run("git commit --allow-empty -m'Dummy commit 2'",
+                       cwd=src_dir)
+        stdout = bb.process.run("git rev-parse HEAD", cwd=src_dir)
+        orig_rev = stdout[0].strip()
+
+        # Fetch and check revision
+        self.d.setVar("SRCREV", "AUTOINC")
+        url = "git://" + src_dir + ";protocol=file;usehead=1;name=newName"
+        fetcher = bb.fetch.Fetch([url], self.d)
+        fetcher.download()
+        fetcher.unpack(self.unpackdir)
+        stdout = bb.process.run("git rev-parse HEAD",
+                                cwd=os.path.join(self.unpackdir, 'git'))
+        unpack_rev = stdout[0].strip()
+        self.assertEqual(orig_rev, unpack_rev)
+
 class FetcherNoNetworkTest(FetcherTest):
     def setUp(self):
         super().setUp()
@@ -824,35 +920,21 @@ class FetcherNetworkTest(FetcherTest):
         self.assertRaises(bb.fetch.FetchError, self.gitfetcher, url1, url2)
 
     @skipIfNoNetwork()
-    def test_gitfetch_localusehead(self):
-        # Create dummy local Git repo
-        src_dir = tempfile.mkdtemp(dir=self.tempdir,
-                                   prefix='gitfetch_localusehead_')
-        src_dir = os.path.abspath(src_dir)
-        bb.process.run("git init", cwd=src_dir)
-        bb.process.run("git commit --allow-empty -m'Dummy commit'",
-                       cwd=src_dir)
-        # Use other branch than master
-        bb.process.run("git checkout -b my-devel", cwd=src_dir)
-        bb.process.run("git commit --allow-empty -m'Dummy commit 2'",
-                       cwd=src_dir)
-        stdout = bb.process.run("git rev-parse HEAD", cwd=src_dir)
-        orig_rev = stdout[0].strip()
-
-        # Fetch and check revision
-        self.d.setVar("SRCREV", "AUTOINC")
-        url = "git://" + src_dir + ";protocol=file;usehead=1"
-        fetcher = bb.fetch.Fetch([url], self.d)
-        fetcher.download()
-        fetcher.unpack(self.unpackdir)
-        stdout = bb.process.run("git rev-parse HEAD",
-                                cwd=os.path.join(self.unpackdir, 'git'))
-        unpack_rev = stdout[0].strip()
-        self.assertEqual(orig_rev, unpack_rev)
+    def test_gitfetch_usehead(self):
+        # Since self.gitfetcher() sets SRCREV we expect this to override
+        # `usehead=1' and instead fetch the specified SRCREV. See
+        # test_local_gitfetch_usehead() for a positive use of the usehead
+        # feature.
+        url = "git://git.openembedded.org/bitbake;usehead=1"
+        self.assertRaises(bb.fetch.ParameterError, self.gitfetcher, url, url)
 
     @skipIfNoNetwork()
-    def test_gitfetch_remoteusehead(self):
-        url = "git://git.openembedded.org/bitbake;usehead=1"
+    def test_gitfetch_usehead_withname(self):
+        # Since self.gitfetcher() sets SRCREV we expect this to override
+        # `usehead=1' and instead fetch the specified SRCREV. See
+        # test_local_gitfetch_usehead() for a positive use of the usehead
+        # feature.
+        url = "git://git.openembedded.org/bitbake;usehead=1;name=newName"
         self.assertRaises(bb.fetch.ParameterError, self.gitfetcher, url, url)
 
     @skipIfNoNetwork()
@@ -903,7 +985,7 @@ class FetcherNetworkTest(FetcherTest):
     def test_git_submodule_dbus_broker(self):
         # The following external repositories have show failures in fetch and unpack operations
         # We want to avoid regressions!
-        url = "gitsm://github.com/bus1/dbus-broker;protocol=git;rev=fc874afa0992d0c75ec25acb43d344679f0ee7d2"
+        url = "gitsm://github.com/bus1/dbus-broker;protocol=git;rev=fc874afa0992d0c75ec25acb43d344679f0ee7d2;branch=main"
         fetcher = bb.fetch.Fetch([url], self.d)
         fetcher.download()
         # Previous cwd has been deleted
@@ -919,7 +1001,7 @@ class FetcherNetworkTest(FetcherTest):
 
     @skipIfNoNetwork()
     def test_git_submodule_CLI11(self):
-        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=bd4dc911847d0cde7a6b41dfa626a85aab213baf"
+        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=bd4dc911847d0cde7a6b41dfa626a85aab213baf;branch=main"
         fetcher = bb.fetch.Fetch([url], self.d)
         fetcher.download()
         # Previous cwd has been deleted
@@ -934,12 +1016,12 @@ class FetcherNetworkTest(FetcherTest):
     @skipIfNoNetwork()
     def test_git_submodule_update_CLI11(self):
         """ Prevent regression on update detection not finding missing submodule, or modules without needed commits """
-        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=cf6a99fa69aaefe477cc52e3ef4a7d2d7fa40714"
+        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=cf6a99fa69aaefe477cc52e3ef4a7d2d7fa40714;branch=main"
         fetcher = bb.fetch.Fetch([url], self.d)
         fetcher.download()
 
         # CLI11 that pulls in a newer nlohmann-json
-        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=49ac989a9527ee9bb496de9ded7b4872c2e0e5ca"
+        url = "gitsm://github.com/CLIUtils/CLI11;protocol=git;rev=49ac989a9527ee9bb496de9ded7b4872c2e0e5ca;branch=main"
         fetcher = bb.fetch.Fetch([url], self.d)
         fetcher.download()
         # Previous cwd has been deleted
@@ -1156,10 +1238,11 @@ class FetchLatestVersionTest(FetcherTest):
         ("mtd-utils", "git://git.yoctoproject.org/mtd-utils.git", "ca39eb1d98e736109c64ff9c1aa2a6ecca222d8f", "")
             : "1.5.0",
         # version pattern "pkg_name-X.Y"
-        ("presentproto", "git://anongit.freedesktop.org/git/xorg/proto/presentproto", "24f3a56e541b0a9e6c6ee76081f441221a120ef9", "")
+        # mirror of git://anongit.freedesktop.org/git/xorg/proto/presentproto since network issues interfered with testing
+        ("presentproto", "git://git.yoctoproject.org/bbfetchtests-presentproto", "24f3a56e541b0a9e6c6ee76081f441221a120ef9", "")
             : "1.0",
         # version pattern "pkg_name-vX.Y.Z"
-        ("dtc", "git://git.qemu.org/dtc.git", "65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf", "")
+        ("dtc", "git://git.yoctoproject.org/bbfetchtests-dtc.git", "65cc4d2748a2c2e6f27f1cf39e07a5dbabd80ebf", "")
             : "1.4.0",
         # combination version pattern
         ("sysprof", "git://gitlab.gnome.org/GNOME/sysprof.git;protocol=https", "cd44ee6644c3641507fb53b8a2a69137f2971219", "")
@@ -1170,7 +1253,8 @@ class FetchLatestVersionTest(FetcherTest):
         ("mobile-broadband-provider-info", "git://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git;protocol=https", "4ed19e11c2975105b71b956440acdb25d46a347d", "")
             : "20120614",
         # packages with a valid UPSTREAM_CHECK_GITTAGREGEX
-        ("xf86-video-omap", "git://anongit.freedesktop.org/xorg/driver/xf86-video-omap", "ae0394e687f1a77e966cf72f895da91840dffb8f", "(?P<pver>(\d+\.(\d\.?)*))")
+                # mirror of git://anongit.freedesktop.org/xorg/driver/xf86-video-omap since network issues interfered with testing
+        ("xf86-video-omap", "git://git.yoctoproject.org/bbfetchtests-xf86-video-omap", "ae0394e687f1a77e966cf72f895da91840dffb8f", "(?P<pver>(\d+\.(\d\.?)*))")
             : "0.4.3",
         ("build-appliance-image", "git://git.yoctoproject.org/poky", "b37dd451a52622d5b570183a81583cc34c2ff555", "(?P<pver>(([0-9][\.|_]?)+[0-9]))")
             : "11.0.0",
@@ -1262,13 +1346,11 @@ class FetchLatestVersionTest(FetcherTest):
 
 
 class FetchCheckStatusTest(FetcherTest):
-    test_wget_uris = ["http://www.cups.org/software/1.7.2/cups-1.7.2-source.tar.bz2",
-                      "http://www.cups.org/",
-                      "http://downloads.yoctoproject.org/releases/sato/sato-engine-0.1.tar.gz",
+    test_wget_uris = ["http://downloads.yoctoproject.org/releases/sato/sato-engine-0.1.tar.gz",
                       "http://downloads.yoctoproject.org/releases/sato/sato-engine-0.2.tar.gz",
                       "http://downloads.yoctoproject.org/releases/sato/sato-engine-0.3.tar.gz",
                       "https://yoctoproject.org/",
-                      "https://yoctoproject.org/documentation",
+                      "https://docs.yoctoproject.org",
                       "http://downloads.yoctoproject.org/releases/opkg/opkg-0.1.7.tar.gz",
                       "http://downloads.yoctoproject.org/releases/opkg/opkg-0.3.0.tar.gz",
                       "ftp://sourceware.org/pub/libffi/libffi-1.20.tar.gz",
@@ -1313,6 +1395,8 @@ class GitMakeShallowTest(FetcherTest):
         self.gitdir = os.path.join(self.tempdir, 'gitshallow')
         bb.utils.mkdirhier(self.gitdir)
         bb.process.run('git init', cwd=self.gitdir)
+        bb.process.run('git config user.email "you@example.com"', cwd=self.gitdir)
+        bb.process.run('git config user.name "Your Name"', cwd=self.gitdir)
 
     def assertRefs(self, expected_refs):
         actual_refs = self.git(['for-each-ref', '--format=%(refname)']).splitlines()
@@ -1436,6 +1520,8 @@ class GitShallowTest(FetcherTest):
 
         bb.utils.mkdirhier(self.srcdir)
         self.git('init', cwd=self.srcdir)
+        self.git('config user.email "you@example.com"', cwd=self.srcdir)
+        self.git('config user.name "Your Name"', cwd=self.srcdir)
         self.d.setVar('WORKDIR', self.tempdir)
         self.d.setVar('S', self.gitdir)
         self.d.delVar('PREMIRRORS')
@@ -1517,6 +1603,7 @@ class GitShallowTest(FetcherTest):
 
         # fetch and unpack, from the shallow tarball
         bb.utils.remove(self.gitdir, recurse=True)
+        bb.process.run('chmod u+w -R "%s"' % ud.clonedir)
         bb.utils.remove(ud.clonedir, recurse=True)
         bb.utils.remove(ud.clonedir.replace('gitsource', 'gitsubmodule'), recurse=True)
 
@@ -1669,6 +1756,8 @@ class GitShallowTest(FetcherTest):
         smdir = os.path.join(self.tempdir, 'gitsubmodule')
         bb.utils.mkdirhier(smdir)
         self.git('init', cwd=smdir)
+        self.git('config user.email "you@example.com"', cwd=smdir)
+        self.git('config user.name "Your Name"', cwd=smdir)
         # Make this look like it was cloned from a remote...
         self.git('config --add remote.origin.url "%s"' % smdir, cwd=smdir)
         self.git('config --add remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"', cwd=smdir)
@@ -1699,6 +1788,8 @@ class GitShallowTest(FetcherTest):
         smdir = os.path.join(self.tempdir, 'gitsubmodule')
         bb.utils.mkdirhier(smdir)
         self.git('init', cwd=smdir)
+        self.git('config user.email "you@example.com"', cwd=smdir)
+        self.git('config user.name "Your Name"', cwd=smdir)
         # Make this look like it was cloned from a remote...
         self.git('config --add remote.origin.url "%s"' % smdir, cwd=smdir)
         self.git('config --add remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"', cwd=smdir)
@@ -1741,8 +1832,8 @@ class GitShallowTest(FetcherTest):
             self.git('annex init', cwd=self.srcdir)
             open(os.path.join(self.srcdir, 'c'), 'w').close()
             self.git('annex add c', cwd=self.srcdir)
-            self.git('commit -m annex-c -a', cwd=self.srcdir)
-            bb.process.run('chmod u+w -R %s' % os.path.join(self.srcdir, '.git', 'annex'))
+            self.git('commit --author "Foo Bar <foo@bar>" -m annex-c -a', cwd=self.srcdir)
+            bb.process.run('chmod u+w -R %s' % self.srcdir)
 
             uri = 'gitannex://%s;protocol=file;subdir=${S}' % self.srcdir
             fetcher, ud = self.fetch_shallow(uri)
@@ -2017,6 +2108,8 @@ class GitLfsTest(FetcherTest):
 
         bb.utils.mkdirhier(self.srcdir)
         self.git('init', cwd=self.srcdir)
+        self.git('config user.email "you@example.com"', cwd=self.srcdir)
+        self.git('config user.name "Your Name"', cwd=self.srcdir)
         with open(os.path.join(self.srcdir, '.gitattributes'), 'wt') as attrs:
             attrs.write('*.mp3 filter=lfs -text')
         self.git(['add', '.gitattributes'], cwd=self.srcdir)
@@ -2031,13 +2124,14 @@ class GitLfsTest(FetcherTest):
             cwd = self.gitdir
         return bb.process.run(cmd, cwd=cwd)[0]
 
-    def fetch(self, uri=None):
+    def fetch(self, uri=None, download=True):
         uris = self.d.getVar('SRC_URI').split()
         uri = uris[0]
         d = self.d
 
         fetcher = bb.fetch2.Fetch(uris, d)
-        fetcher.download()
+        if download:
+            fetcher.download()
         ud = fetcher.ud[uri]
         return fetcher, ud
 
@@ -2047,16 +2141,21 @@ class GitLfsTest(FetcherTest):
         uri = 'git://%s;protocol=file;subdir=${S};lfs=1' % self.srcdir
         self.d.setVar('SRC_URI', uri)
 
-        fetcher, ud = self.fetch()
+        # Careful: suppress initial attempt at downloading until
+        # we know whether git-lfs is installed.
+        fetcher, ud = self.fetch(uri=None, download=False)
         self.assertIsNotNone(ud.method._find_git_lfs)
 
-        # If git-lfs can be found, the unpack should be successful
-        ud.method._find_git_lfs = lambda d: True
-        shutil.rmtree(self.gitdir, ignore_errors=True)
-        fetcher.unpack(self.d.getVar('WORKDIR'))
+        # If git-lfs can be found, the unpack should be successful. Only
+        # attempt this with the real live copy of git-lfs installed.
+        if ud.method._find_git_lfs(self.d):
+            fetcher.download()
+            shutil.rmtree(self.gitdir, ignore_errors=True)
+            fetcher.unpack(self.d.getVar('WORKDIR'))
 
         # If git-lfs cannot be found, the unpack should throw an error
         with self.assertRaises(bb.fetch2.FetchError):
+            fetcher.download()
             ud.method._find_git_lfs = lambda d: False
             shutil.rmtree(self.gitdir, ignore_errors=True)
             fetcher.unpack(self.d.getVar('WORKDIR'))
@@ -2067,10 +2166,16 @@ class GitLfsTest(FetcherTest):
         uri = 'git://%s;protocol=file;subdir=${S};lfs=0' % self.srcdir
         self.d.setVar('SRC_URI', uri)
 
+        # In contrast to test_lfs_enabled(), allow the implicit download
+        # done by self.fetch() to occur here. The point of this test case
+        # is to verify that the fetcher can survive even if the source
+        # repository has Git LFS usage configured.
         fetcher, ud = self.fetch()
         self.assertIsNotNone(ud.method._find_git_lfs)
 
-        # If git-lfs can be found, the unpack should be successful
+        # If git-lfs can be found, the unpack should be successful. A
+        # live copy of git-lfs is not required for this case, so
+        # unconditionally forge its presence.
         ud.method._find_git_lfs = lambda d: True
         shutil.rmtree(self.gitdir, ignore_errors=True)
         fetcher.unpack(self.d.getVar('WORKDIR'))
@@ -2080,6 +2185,38 @@ class GitLfsTest(FetcherTest):
         shutil.rmtree(self.gitdir, ignore_errors=True)
         fetcher.unpack(self.d.getVar('WORKDIR'))
 
+class GitURLWithSpacesTest(FetcherTest):
+    test_git_urls = {
+        "git://tfs-example.org:22/tfs/example%20path/example.git" : {
+            'url': 'git://tfs-example.org:22/tfs/example%20path/example.git',
+            'gitsrcname': 'tfs-example.org.22.tfs.example_path.example.git',
+            'path': '/tfs/example path/example.git'
+        },
+        "git://tfs-example.org:22/tfs/example%20path/example%20repo.git" : {
+            'url': 'git://tfs-example.org:22/tfs/example%20path/example%20repo.git',
+            'gitsrcname': 'tfs-example.org.22.tfs.example_path.example_repo.git',
+            'path': '/tfs/example path/example repo.git'
+        }
+    }
+
+    def test_urls(self):
+
+        # Set fake SRCREV to stop git fetcher from trying to contact non-existent git repo
+        self.d.setVar('SRCREV', '82ea737a0b42a8b53e11c9cde141e9e9c0bd8c40')
+
+        for test_git_url, ref in self.test_git_urls.items():
+
+            fetcher = bb.fetch.Fetch([test_git_url], self.d)
+            ud = fetcher.ud[fetcher.urls[0]]
+
+            self.assertEqual(ud.url, ref['url'])
+            self.assertEqual(ud.path, ref['path'])
+            self.assertEqual(ud.localfile, os.path.join(self.dldir, "git2", ref['gitsrcname']))
+            self.assertEqual(ud.localpath, os.path.join(self.dldir, "git2", ref['gitsrcname']))
+            self.assertEqual(ud.lockfile, os.path.join(self.dldir, "git2", ref['gitsrcname'] + '.lock'))
+            self.assertEqual(ud.clonedir, os.path.join(self.dldir, "git2", ref['gitsrcname']))
+            self.assertEqual(ud.fullmirror, os.path.join(self.dldir, "git2_" + ref['gitsrcname'] + '.tar.gz'))
+
 class NPMTest(FetcherTest):
     def skipIfNoNpm():
         import shutil
diff --git a/bitbake/lib/bb/tests/parse.py b/bitbake/lib/bb/tests/parse.py
index 9afd1b20..9e21e184 100644
--- a/bitbake/lib/bb/tests/parse.py
+++ b/bitbake/lib/bb/tests/parse.py
@@ -178,7 +178,10 @@ python () {
 addtask do_patch after do_foo after do_unpack before do_configure before do_compile
 addtask do_fetch do_patch
 
-deltask do_fetch do_patch
+MYVAR = "do_patch"
+EMPTYVAR = ""
+deltask do_fetch ${MYVAR} ${EMPTYVAR}
+deltask ${EMPTYVAR}
 """
     def test_parse_addtask_deltask(self):
         import sys
@@ -189,6 +192,5 @@ deltask do_fetch do_patch
         self.assertTrue("addtask contained multiple 'before' keywords" in stdout)
         self.assertTrue("addtask contained multiple 'after' keywords" in stdout)
         self.assertTrue('addtask ignored: " do_patch"' in stdout)
-        self.assertTrue('deltask ignored: " do_patch"' in stdout)
         #self.assertTrue('dependent task do_foo for do_patch does not exist' in stdout)
 
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf
index 5e451fc2..efebf001 100644
--- a/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf
+++ b/bitbake/lib/bb/tests/runqueue-tests/conf/bitbake.conf
@@ -1,7 +1,8 @@
 CACHE = "${TOPDIR}/cache"
 THISDIR = "${@os.path.dirname(d.getVar('FILE'))}"
 COREBASE := "${@os.path.normpath(os.path.dirname(d.getVar('FILE')+'/../../'))}"
-BBFILES = "${COREBASE}/recipes/*.bb"
+EXTRA_BBFILES ?= ""
+BBFILES = "${COREBASE}/recipes/*.bb ${EXTRA_BBFILES}"
 PROVIDES = "${PN}"
 PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0]}"
 PF = "${BB_CURRENT_MC}:${PN}"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc-1.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc-1.conf
new file mode 100644
index 00000000..f34b8dcc
--- /dev/null
+++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc-1.conf
@@ -0,0 +1,2 @@
+TMPDIR = "${TOPDIR}/mc1/"
+BBMASK += "recipes/fails-mc/fails-mc1.bb"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf
deleted file mode 100644
index ecf23e1c..00000000
--- a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc1.conf
+++ /dev/null
@@ -1 +0,0 @@
-TMPDIR = "${TOPDIR}/mc1/"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf
deleted file mode 100644
index eef338e4..00000000
--- a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc2.conf
+++ /dev/null
@@ -1 +0,0 @@
-TMPDIR = "${TOPDIR}/mc2/"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc_2.conf b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc_2.conf
new file mode 100644
index 00000000..c3360fc5
--- /dev/null
+++ b/bitbake/lib/bb/tests/runqueue-tests/conf/multiconfig/mc_2.conf
@@ -0,0 +1,2 @@
+TMPDIR = "${TOPDIR}/mc2/"
+BBMASK += "recipes/fails-mc/fails-mc2.bb"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/recipes/f1.bb b/bitbake/lib/bb/tests/runqueue-tests/recipes/f1.bb
new file mode 100644
index 00000000..7b8fc592
--- /dev/null
+++ b/bitbake/lib/bb/tests/runqueue-tests/recipes/f1.bb
@@ -0,0 +1 @@
+do_install[mcdepends] = "mc:mc-1:mc_2:a1:do_build"
diff --git a/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc1.bb b/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc1.bb
new file mode 100644
index 00000000..eed69c80
--- /dev/null
+++ b/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc1.bb
@@ -0,0 +1,5 @@
+python () {
+    if d.getVar("BB_CURRENT_MC") == "mc-1":
+        bb.fatal("Multiconfig is mc-1")
+}
+
diff --git a/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc2.bb b/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc2.bb
new file mode 100644
index 00000000..3c172ef9
--- /dev/null
+++ b/bitbake/lib/bb/tests/runqueue-tests/recipes/fails-mc/fails-mc2.bb
@@ -0,0 +1,4 @@
+python () {
+    if d.getVar("BB_CURRENT_MC") == "mc_2":
+        bb.fatal("Multiconfig is mc_2")
+}
diff --git a/bitbake/lib/bb/tests/runqueue.py b/bitbake/lib/bb/tests/runqueue.py
index 4ba12a07..4f335b8f 100644
--- a/bitbake/lib/bb/tests/runqueue.py
+++ b/bitbake/lib/bb/tests/runqueue.py
@@ -216,22 +216,67 @@ class RunQueueTests(unittest.TestCase):
     def test_multiconfig_setscene_optimise(self):
         with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir:
             extraenv = {
-                "BBMULTICONFIG" : "mc1 mc2",
+                "BBMULTICONFIG" : "mc-1 mc_2",
                 "BB_SIGNATURE_HANDLER" : "basic"
             }
-            cmd = ["bitbake", "b1", "mc:mc1:b1", "mc:mc2:b1"]
+            cmd = ["bitbake", "b1", "mc:mc-1:b1", "mc:mc_2:b1"]
             setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene',
                              'populate_sysroot_setscene', 'package_qa_setscene']
             sstatevalid = ""
             tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv)
             expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + \
-                       ['mc1:b1:' + x for x in setscenetasks] + ['mc1:a1:' + x for x in setscenetasks] + \
-                       ['mc2:b1:' + x for x in setscenetasks] + ['mc2:a1:' + x for x in setscenetasks] + \
-                       ['mc1:b1:build', 'mc2:b1:build']
-            for x in ['mc1:a1:package_qa_setscene', 'mc2:a1:package_qa_setscene', 'a1:build', 'a1:package_qa']:
+                       ['mc-1:b1:' + x for x in setscenetasks] + ['mc-1:a1:' + x for x in setscenetasks] + \
+                       ['mc_2:b1:' + x for x in setscenetasks] + ['mc_2:a1:' + x for x in setscenetasks] + \
+                       ['mc-1:b1:build', 'mc_2:b1:build']
+            for x in ['mc-1:a1:package_qa_setscene', 'mc_2:a1:package_qa_setscene', 'a1:build', 'a1:package_qa']:
                 expected.remove(x)
             self.assertEqual(set(tasks), set(expected))
 
+    def test_multiconfig_bbmask(self):
+        # This test validates that multiconfigs can independently mask off
+        # recipes they do not want with BBMASK. It works by having recipes
+        # that will fail to parse for mc-1 and mc_2, then making each multiconfig
+        # build the one that does parse. This ensures that the recipes are in
+        # each multiconfigs BBFILES, but each is masking only the one that
+        # doesn't parse
+        with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir:
+            extraenv = {
+                "BBMULTICONFIG" : "mc-1 mc_2",
+                "BB_SIGNATURE_HANDLER" : "basic",
+                "EXTRA_BBFILES": "${COREBASE}/recipes/fails-mc/*.bb",
+            }
+            cmd = ["bitbake", "mc:mc-1:fails-mc2", "mc:mc_2:fails-mc1"]
+            self.run_bitbakecmd(cmd, tempdir, "", extraenv=extraenv)
+
+    def test_multiconfig_mcdepends(self):
+        with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir:
+            extraenv = {
+                "BBMULTICONFIG" : "mc-1 mc_2",
+                "BB_SIGNATURE_HANDLER" : "TestMulticonfigDepends",
+                "EXTRA_BBFILES": "${COREBASE}/recipes/fails-mc/*.bb",
+            }
+            tasks = self.run_bitbakecmd(["bitbake", "mc:mc-1:f1"], tempdir, "", extraenv=extraenv, cleanup=True)
+            expected = ["mc-1:f1:%s" % t for t in self.alltasks] + \
+                       ["mc_2:a1:%s" % t for t in self.alltasks]
+            self.assertEqual(set(tasks), set(expected))
+
+            # A rebuild does nothing
+            tasks = self.run_bitbakecmd(["bitbake", "mc:mc-1:f1"], tempdir, "", extraenv=extraenv, cleanup=True)
+            self.assertEqual(set(tasks), set())
+
+            # Test that a signature change in the dependent task causes
+            # mcdepends to rebuild
+            tasks = self.run_bitbakecmd(["bitbake", "mc:mc_2:a1", "-c", "compile", "-f"], tempdir, "", extraenv=extraenv, cleanup=True)
+            expected = ["mc_2:a1:compile"]
+            self.assertEqual(set(tasks), set(expected))
+
+            rerun_tasks = self.alltasks[:]
+            for x in ("fetch", "unpack", "patch", "prepare_recipe_sysroot", "configure", "compile"):
+                rerun_tasks.remove(x)
+            tasks = self.run_bitbakecmd(["bitbake", "mc:mc-1:f1"], tempdir, "", extraenv=extraenv, cleanup=True)
+            expected = ["mc-1:f1:%s" % t for t in rerun_tasks] + \
+                       ["mc_2:a1:%s" % t for t in rerun_tasks]
+            self.assertEqual(set(tasks), set(expected))
 
     @unittest.skipIf(sys.version_info < (3, 5, 0), 'Python 3.5 or later required')
     def test_hashserv_single(self):
@@ -316,7 +361,7 @@ class RunQueueTests(unittest.TestCase):
 
     def shutdown(self, tempdir):
         # Wait for the hashserve socket to disappear else we'll see races with the tempdir cleanup
-        while os.path.exists(tempdir + "/hashserve.sock"):
+        while (os.path.exists(tempdir + "/hashserve.sock") or os.path.exists(tempdir + "cache/hashserv.db-wal")):
             time.sleep(0.5)
 
 
diff --git a/bitbake/lib/bb/tests/siggen.py b/bitbake/lib/bb/tests/siggen.py
new file mode 100644
index 00000000..c21ab4e4
--- /dev/null
+++ b/bitbake/lib/bb/tests/siggen.py
@@ -0,0 +1,91 @@
+#
+# BitBake Test for lib/bb/siggen.py
+#
+# Copyright (C) 2020 Jean-François Dagenais
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import unittest
+import logging
+import bb
+import time
+
+logger = logging.getLogger('BitBake.TestSiggen')
+
+import bb.siggen
+
+class SiggenTest(unittest.TestCase):
+
+    def test_clean_basepath_simple_target_basepath(self):
+        basepath = '/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+    def test_clean_basepath_basic_virtual_basepath(self):
+        basepath = 'virtual:something:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask:virtual:something'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+    def test_clean_basepath_mc_basepath(self):
+        basepath = 'mc:somemachine:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask:mc:somemachine'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+    def test_clean_basepath_virtual_long_prefix_basepath(self):
+        basepath = 'virtual:something:A:B:C:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask:virtual:something:A:B:C'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+    def test_clean_basepath_mc_virtual_basepath(self):
+        basepath = 'mc:somemachine:virtual:something:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask:virtual:something:mc:somemachine'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+    def test_clean_basepath_mc_virtual_long_prefix_basepath(self):
+        basepath = 'mc:X:virtual:something:C:B:A:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask'
+        expected_cleaned = 'helloworld/helloworld_1.2.3.bb:do_sometask:virtual:something:C:B:A:mc:X'
+
+        actual_cleaned = bb.siggen.clean_basepath(basepath)
+
+        self.assertEqual(actual_cleaned, expected_cleaned)
+
+
+    # def test_clean_basepath_performance(self):
+    #     input_basepaths = [
+    #         'mc:X:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         'mc:X:virtual:something:C:B:A:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         'virtual:something:C:B:A:/different/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         'virtual:something:A:/full/path/to/poky/meta/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         '/this/is/most/common/input/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         '/and/should/be/tested/with/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #         '/more/weight/recipes-whatever/helloworld/helloworld_1.2.3.bb:do_sometask',
+    #     ]
+
+    #     time_start = time.time()
+
+    #     i = 2000000
+    #     while i >= 0:
+    #         for basepath in input_basepaths:
+    #             bb.siggen.clean_basepath(basepath)
+    #         i -= 1
+
+    #     elapsed = time.time() - time_start
+    #     print('{} ({}s)'.format(self.id(), round(elapsed, 3)))
+
+    #     self.assertTrue(False)
diff --git a/bitbake/lib/bb/tinfoil.py b/bitbake/lib/bb/tinfoil.py
index 8c9b6b8c..796a98f0 100644
--- a/bitbake/lib/bb/tinfoil.py
+++ b/bitbake/lib/bb/tinfoil.py
@@ -22,7 +22,6 @@ import bb.taskdata
 import bb.utils
 import bb.command
 import bb.remotedata
-from bb.cookerdata import CookerConfiguration
 from bb.main import setup_bitbake, BitBakeConfigParameters
 import bb.fetch2
 
@@ -117,15 +116,16 @@ class TinfoilCookerAdapter:
 
     class TinfoilCookerCollectionAdapter:
         """ cooker.collection adapter """
-        def __init__(self, tinfoil):
+        def __init__(self, tinfoil, mc=''):
             self.tinfoil = tinfoil
+            self.mc = mc
         def get_file_appends(self, fn):
-            return self.tinfoil.get_file_appends(fn)
+            return self.tinfoil.get_file_appends(fn, self.mc)
         def __getattr__(self, name):
             if name == 'overlayed':
-                return self.tinfoil.get_overlayed_recipes()
+                return self.tinfoil.get_overlayed_recipes(self.mc)
             elif name == 'bbappends':
-                return self.tinfoil.run_command('getAllAppends')
+                return self.tinfoil.run_command('getAllAppends', self.mc)
             else:
                 raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
 
@@ -185,10 +185,11 @@ class TinfoilCookerAdapter:
 
     def __init__(self, tinfoil):
         self.tinfoil = tinfoil
-        self.collection = self.TinfoilCookerCollectionAdapter(tinfoil)
+        self.multiconfigs = [''] + (tinfoil.config_data.getVar('BBMULTICONFIG') or '').split()
+        self.collections = {}
         self.recipecaches = {}
-        self.recipecaches[''] = self.TinfoilRecipeCacheAdapter(tinfoil)
-        for mc in (tinfoil.config_data.getVar('BBMULTICONFIG') or '').split():
+        for mc in self.multiconfigs:
+            self.collections[mc] = self.TinfoilCookerCollectionAdapter(tinfoil, mc)
             self.recipecaches[mc] = self.TinfoilRecipeCacheAdapter(tinfoil, mc)
         self._cache = {}
     def __getattr__(self, name):
@@ -379,18 +380,13 @@ class Tinfoil:
         if not config_params:
             config_params = TinfoilConfigParameters(config_only=config_only, quiet=quiet)
 
-        cookerconfig = CookerConfiguration()
-        cookerconfig.setConfigParameters(config_params)
-
         if not config_only:
             # Disable local loggers because the UI module is going to set up its own
             for handler in self.localhandlers:
                 self.logger.handlers.remove(handler)
             self.localhandlers = []
 
-        self.server_connection, ui_module = setup_bitbake(config_params,
-                            cookerconfig,
-                            extrafeatures)
+        self.server_connection, ui_module = setup_bitbake(config_params, extrafeatures)
 
         self.ui_module = ui_module
 
@@ -444,7 +440,7 @@ class Tinfoil:
         to initialise Tinfoil and use it with config_only=True first and
         then conditionally call this function to parse recipes later.
         """
-        config_params = TinfoilConfigParameters(config_only=False)
+        config_params = TinfoilConfigParameters(config_only=False, quiet=self.quiet)
         self.run_actions(config_params)
         self.recipes_parsed = True
 
@@ -465,7 +461,16 @@ class Tinfoil:
         commandline = [command]
         if params:
             commandline.extend(params)
-        result = self.server_connection.connection.runCommand(commandline)
+        try:
+            result = self.server_connection.connection.runCommand(commandline)
+        finally:
+            while True:
+                event = self.wait_event()
+                if not event:
+                    break
+                if isinstance(event, logging.LogRecord):
+                    if event.taskpid == 0 or event.levelno > logging.INFO:
+                        self.logger.handle(event)
         if result[1]:
             raise TinfoilCommandFailed(result[1])
         return result[0]
@@ -492,11 +497,11 @@ class Tinfoil:
             raise Exception('Not connected to server (did you call .prepare()?)')
         return self.server_connection.events.waitEvent(timeout)
 
-    def get_overlayed_recipes(self):
+    def get_overlayed_recipes(self, mc=''):
         """
         Find recipes which are overlayed (i.e. where recipes exist in multiple layers)
         """
-        return defaultdict(list, self.run_command('getOverlayedRecipes'))
+        return defaultdict(list, self.run_command('getOverlayedRecipes', mc))
 
     def get_skipped_recipes(self):
         """
@@ -534,11 +539,11 @@ class Tinfoil:
                 raise bb.providers.NoProvider('Unable to find any recipe file matching "%s"' % pn)
         return best[3]
 
-    def get_file_appends(self, fn):
+    def get_file_appends(self, fn, mc=''):
         """
         Find the bbappends for a recipe file
         """
-        return self.run_command('getFileAppends', fn)
+        return self.run_command('getFileAppends', fn, mc)
 
     def all_recipes(self, mc='', sort=True):
         """
@@ -736,7 +741,7 @@ class Tinfoil:
                                 continue
                             if helper.eventHandler(event):
                                 if isinstance(event, bb.build.TaskFailedSilent):
-                                    logger.warning("Logfile for failed setscene task is %s" % event.logfile)
+                                    self.logger.warning("Logfile for failed setscene task is %s" % event.logfile)
                                 elif isinstance(event, bb.build.TaskFailed):
                                     bb.ui.knotty.print_event_log(event, includelogs, loglines, termfilter)
                                 continue
@@ -810,18 +815,22 @@ class Tinfoil:
         prepare() has been called, or use a with... block when you create
         the tinfoil object which will ensure that it gets called.
         """
-        if self.server_connection:
-            self.run_command('clientComplete')
-            _server_connections.remove(self.server_connection)
-            bb.event.ui_queue = []
-            self.server_connection.terminate()
-            self.server_connection = None
-
-        # Restore logging handlers to how it looked when we started
-        if self.oldhandlers:
-            for handler in self.logger.handlers:
-                if handler not in self.oldhandlers:
-                    self.logger.handlers.remove(handler)
+        try:
+            if self.server_connection:
+                try:
+                    self.run_command('clientComplete')
+                finally:
+                    _server_connections.remove(self.server_connection)
+                    bb.event.ui_queue = []
+                    self.server_connection.terminate()
+                    self.server_connection = None
+
+        finally:
+            # Restore logging handlers to how it looked when we started
+            if self.oldhandlers:
+                for handler in self.logger.handlers:
+                    if handler not in self.oldhandlers:
+                        self.logger.handlers.remove(handler)
 
     def _reconvert_type(self, obj, origtypename):
         """
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 82c62e33..43aa5928 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -148,14 +148,14 @@ class ORMWrapper(object):
         buildrequest = None
         if brbe is not None:
             # Toaster-triggered build
-            logger.debug(1, "buildinfohelper: brbe is %s" % brbe)
+            logger.debug("buildinfohelper: brbe is %s" % brbe)
             br, _ = brbe.split(":")
             buildrequest = BuildRequest.objects.get(pk=br)
             prj = buildrequest.project
         else:
             # CLI build
             prj = Project.objects.get_or_create_default_project()
-            logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj)
+            logger.debug("buildinfohelper: project is not specified, defaulting to %s" % prj)
 
         if buildrequest is not None:
             # reuse existing Build object
@@ -171,7 +171,7 @@ class ORMWrapper(object):
                 completed_on=now,
                 build_name='')
 
-        logger.debug(1, "buildinfohelper: build is created %s" % build)
+        logger.debug("buildinfohelper: build is created %s" % build)
 
         if buildrequest is not None:
             buildrequest.build = build
@@ -906,7 +906,7 @@ class BuildInfoHelper(object):
 
         self.project = None
 
-        logger.debug(1, "buildinfohelper: Build info helper inited %s" % vars(self))
+        logger.debug("buildinfohelper: Build info helper inited %s" % vars(self))
 
 
     ###################
@@ -1620,7 +1620,7 @@ class BuildInfoHelper(object):
             # if we have a backlog of events, do our best to save them here
             if len(self.internal_state['backlog']):
                 tempevent = self.internal_state['backlog'].pop()
-                logger.debug(1, "buildinfohelper: Saving stored event %s "
+                logger.debug("buildinfohelper: Saving stored event %s "
                              % tempevent)
                 self.store_log_event(tempevent,cli_backlog)
             else:
diff --git a/bitbake/lib/bb/ui/knotty.py b/bitbake/lib/bb/ui/knotty.py
index 87e873d6..04285eac 100644
--- a/bitbake/lib/bb/ui/knotty.py
+++ b/bitbake/lib/bb/ui/knotty.py
@@ -144,7 +144,7 @@ class TerminalFilter(object):
                 pass
         if not cr:
             try:
-                cr = (env['LINES'], env['COLUMNS'])
+                cr = (os.environ['LINES'], os.environ['COLUMNS'])
             except:
                 cr = (25, 80)
         return cr
@@ -380,14 +380,27 @@ _evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.Lo
               "bb.event.BuildBase", "bb.build.TaskStarted", "bb.build.TaskSucceeded", "bb.build.TaskFailedSilent",
               "bb.build.TaskProgress", "bb.event.ProcessStarted", "bb.event.ProcessProgress", "bb.event.ProcessFinished"]
 
+def drain_events_errorhandling(eventHandler):
+    # We don't have logging setup, we do need to show any events we see before exiting
+    event = True
+    logger = bb.msg.logger_create('bitbake', sys.stdout)
+    while event:
+        event = eventHandler.waitEvent(0)
+        if isinstance(event, logging.LogRecord):
+            logger.handle(event)
+
 def main(server, eventHandler, params, tf = TerminalFilter):
 
-    if not params.observe_only:
-        params.updateToServer(server, os.environ.copy())
+    try:
+        if not params.observe_only:
+            params.updateToServer(server, os.environ.copy())
 
-    includelogs, loglines, consolelogfile, logconfigfile = _log_settings_from_server(server, params.observe_only)
+        includelogs, loglines, consolelogfile, logconfigfile = _log_settings_from_server(server, params.observe_only)
 
-    loglevel, _ = bb.msg.constructLogOptions()
+        loglevel, _ = bb.msg.constructLogOptions()
+    except bb.BBHandledException:
+        drain_events_errorhandling(eventHandler)
+        return 1
 
     if params.options.quiet == 0:
         console_loglevel = loglevel
@@ -679,7 +692,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
                 if not parseprogress:
                     continue
                 parseprogress.finish()
-                pasreprogress = None
+                parseprogress = None
                 if params.options.quiet == 0:
                     print(("Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                         % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
@@ -732,7 +745,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
                 continue
 
             if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
-                logger.info("Running setscene task %d of %d (%s)" % (event.stats.completed + event.stats.active + event.stats.failed + 1, event.stats.total, event.taskstring))
+                logger.info("Running setscene task %d of %d (%s)" % (event.stats.setscene_covered + event.stats.setscene_active + event.stats.setscene_notcovered + 1, event.stats.setscene_total, event.taskstring))
                 continue
 
             if isinstance(event, bb.runqueue.runQueueTaskStarted):
diff --git a/bitbake/lib/bb/ui/ncurses.py b/bitbake/lib/bb/ui/ncurses.py
index da4fbeab..cf1c876a 100644
--- a/bitbake/lib/bb/ui/ncurses.py
+++ b/bitbake/lib/bb/ui/ncurses.py
@@ -48,6 +48,8 @@ import bb
 import xmlrpc.client
 from bb.ui import uihelper
 
+logger = logging.getLogger(__name__)
+
 parsespin = itertools.cycle( r'|/-\\' )
 
 X = 0
diff --git a/bitbake/lib/bb/ui/taskexp.py b/bitbake/lib/bb/ui/taskexp.py
index 05e32338..2b246710 100644
--- a/bitbake/lib/bb/ui/taskexp.py
+++ b/bitbake/lib/bb/ui/taskexp.py
@@ -58,7 +58,12 @@ class PackageReverseDepView(Gtk.TreeView):
         self.current = None
         self.filter_model = model.filter_new()
         self.filter_model.set_visible_func(self._filter)
-        self.sort_model = self.filter_model.sort_new_with_model()
+        # The introspected API was fixed but we can't rely on a pygobject that hides this.
+        # https://gitlab.gnome.org/GNOME/pygobject/-/commit/9cdbc56fbac4db2de78dc080934b8f0a7efc892a
+        if hasattr(Gtk.TreeModelSort, "new_with_model"):
+            self.sort_model = Gtk.TreeModelSort.new_with_model(self.filter_model)
+        else:
+            self.sort_model = self.filter_model.sort_new_with_model()
         self.sort_model.set_sort_column_id(COL_DEP_PARENT, Gtk.SortType.ASCENDING)
         self.set_model(self.sort_model)
         self.append_column(Gtk.TreeViewColumn(label, Gtk.CellRendererText(), text=COL_DEP_PARENT))
diff --git a/bitbake/lib/bb/ui/toasterui.py b/bitbake/lib/bb/ui/toasterui.py
index 9260f5d9..ec5bd4f1 100644
--- a/bitbake/lib/bb/ui/toasterui.py
+++ b/bitbake/lib/bb/ui/toasterui.py
@@ -131,6 +131,10 @@ def main(server, eventHandler, params):
 
     helper = uihelper.BBUIHelper()
 
+    if not params.observe_only:
+        params.updateToServer(server, os.environ.copy())
+        params.updateFromServer(server)
+
     # TODO don't use log output to determine when bitbake has started
     #
     # WARNING: this log handler cannot be removed, as localhostbecontroller
@@ -162,8 +166,6 @@ def main(server, eventHandler, params):
         logger.warning("buildstats is not enabled. Please enable INHERIT += \"buildstats\" to generate build statistics.")
 
     if not params.observe_only:
-        params.updateFromServer(server)
-        params.updateToServer(server, os.environ.copy())
         cmdline = params.parseActions()
         if not cmdline:
             print("Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
diff --git a/bitbake/lib/bb/ui/uievent.py b/bitbake/lib/bb/ui/uievent.py
index 13d0d4a0..8607d052 100644
--- a/bitbake/lib/bb/ui/uievent.py
+++ b/bitbake/lib/bb/ui/uievent.py
@@ -11,9 +11,13 @@ server and queue them for the UI to process. This process must be used to avoid
 client/server deadlocks.
 """
 
-import socket, threading, pickle, collections
+import collections, logging, pickle, socket, threading
 from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
 
+import bb
+
+logger = logging.getLogger(__name__)
+
 class BBUIEventQueue:
     def __init__(self, BBServer, clientinfo=("localhost, 0")):
 
diff --git a/bitbake/lib/bb/ui/uihelper.py b/bitbake/lib/bb/ui/uihelper.py
index 48d808ae..52fdae3f 100644
--- a/bitbake/lib/bb/ui/uihelper.py
+++ b/bitbake/lib/bb/ui/uihelper.py
@@ -49,8 +49,8 @@ class BBUIHelper:
             tid = event._fn + ":" + event._task
             removetid(event.pid, tid)
             self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)})
-        elif isinstance(event, bb.runqueue.runQueueTaskStarted):
-            self.tasknumber_current = event.stats.completed + event.stats.active + event.stats.failed + 1
+        elif isinstance(event, bb.runqueue.runQueueTaskStarted) or isinstance(event, bb.runqueue.sceneQueueTaskStarted):
+            self.tasknumber_current = event.stats.completed + event.stats.active + event.stats.failed + event.stats.setscene_active + 1
             self.tasknumber_total = event.stats.total
             self.needUpdate = True
         elif isinstance(event, bb.build.TaskProgress):
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py
index 5f5767c1..b282d09a 100644
--- a/bitbake/lib/bb/utils.py
+++ b/bitbake/lib/bb/utils.py
@@ -129,6 +129,7 @@ def vercmp(ta, tb):
     return r
 
 def vercmp_string(a, b):
+    """ Split version strings and compare them """
     ta = split_version(a)
     tb = split_version(b)
     return vercmp(ta, tb)
@@ -247,6 +248,12 @@ def explode_dep_versions2(s, *, sort=True):
     return r
 
 def explode_dep_versions(s):
+    """
+    Take an RDEPENDS style string of format:
+    "DEPEND1 (optional version) DEPEND2 (optional version) ..."
+    skip null value and items appeared in dependancy string multiple times
+    and return a dictionary of dependencies and versions.
+    """
     r = explode_dep_versions2(s)
     for d in r:
         if not r[d]:
@@ -402,8 +409,8 @@ def better_exec(code, context, text = None, realfile = "<code>", pythonexception
         (t, value, tb) = sys.exc_info()
         try:
             _print_exception(t, value, tb, realfile, text, context)
-        except Exception as e:
-            logger.error("Exception handler error: %s" % str(e))
+        except Exception as e2:
+            logger.error("Exception handler error: %s" % str(e2))
 
         e = bb.BBHandledException(e)
         raise e
@@ -433,20 +440,6 @@ def fileslocked(files):
         for lock in locks:
             bb.utils.unlockfile(lock)
 
-@contextmanager
-def timeout(seconds):
-    def timeout_handler(signum, frame):
-        pass
-
-    original_handler = signal.signal(signal.SIGALRM, timeout_handler)
-
-    try:
-        signal.alarm(seconds)
-        yield
-    finally:
-        signal.alarm(0)
-        signal.signal(signal.SIGALRM, original_handler)
-
 def lockfile(name, shared=False, retry=True, block=False):
     """
     Use the specified file as a lock file, return when the lock has
@@ -580,7 +573,6 @@ def preserved_envvars_exported():
         'PATH',
         'PWD',
         'SHELL',
-        'TERM',
         'USER',
         'LC_ALL',
         'BBSERVER',
@@ -617,7 +609,7 @@ def filter_environment(good_vars):
     os.environ["LC_ALL"] = "en_US.UTF-8"
 
     if removed_vars:
-        logger.debug(1, "Removed the following variables from the environment: %s", ", ".join(removed_vars.keys()))
+        logger.debug("Removed the following variables from the environment: %s", ", ".join(removed_vars.keys()))
 
     return removed_vars
 
@@ -707,7 +699,7 @@ def remove(path, recurse=False, ionice=False):
                 raise
 
 def prunedir(topdir, ionice=False):
-    # Delete everything reachable from the directory named in 'topdir'.
+    """ Delete everything reachable from the directory named in 'topdir'. """
     # CAUTION:  This is dangerous!
     if _check_unsafe_delete_path(topdir):
         raise Exception('bb.utils.prunedir: called with dangerous path "%s", refusing to delete!' % topdir)
@@ -718,8 +710,10 @@ def prunedir(topdir, ionice=False):
 # but thats possibly insane and suffixes is probably going to be small
 #
 def prune_suffix(var, suffixes, d):
-    # See if var ends with any of the suffixes listed and
-    # remove it if found
+    """ 
+    See if var ends with any of the suffixes listed and
+    remove it if found 
+    """
     for suffix in suffixes:
         if suffix and var.endswith(suffix):
             return var[:-len(suffix)]
@@ -959,7 +953,22 @@ def which(path, item, direction = 0, history = False, executable=False):
         return "", hist
     return ""
 
+@contextmanager
+def umask(new_mask):
+    """
+    Context manager to set the umask to a specific mask, and restore it afterwards.
+    """
+    current_mask = os.umask(new_mask)
+    try:
+        yield
+    finally:
+        os.umask(current_mask)
+
 def to_boolean(string, default=None):
+    """ 
+    Check input string and return boolean value True/False/None
+    depending upon the checks 
+    """
     if not string:
         return default
 
@@ -1003,6 +1012,23 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
     return falsevalue
 
 def contains_any(variable, checkvalues, truevalue, falsevalue, d):
+    """Check if a variable contains any values specified.
+
+    Arguments:
+
+    variable -- the variable name. This will be fetched and expanded (using
+    d.getVar(variable)) and then split into a set().
+
+    checkvalues -- if this is a string it is split on whitespace into a set(),
+    otherwise coerced directly into a set().
+
+    truevalue -- the value to return if checkvalues is a subset of variable.
+
+    falsevalue -- the value to return if variable is empty or if checkvalues is
+    not a subset of variable.
+
+    d -- the data store.
+    """
     val = d.getVar(variable)
     if not val:
         return falsevalue
@@ -1086,21 +1112,20 @@ def process_profilelog(fn, pout = None):
     # Either call with a list of filenames and set pout or a filename and optionally pout.
     if not pout:
         pout = fn + '.processed'
-    pout = open(pout, 'w')
-   
-    import pstats
-    if isinstance(fn, list):
-        p = pstats.Stats(*fn, stream=pout)
-    else:
-        p = pstats.Stats(fn, stream=pout)
-    p.sort_stats('time')
-    p.print_stats()
-    p.print_callers()
-    p.sort_stats('cumulative')
-    p.print_stats()
 
-    pout.flush()
-    pout.close()  
+    with open(pout, 'w') as pout:
+        import pstats
+        if isinstance(fn, list):
+            p = pstats.Stats(*fn, stream=pout)
+        else:
+            p = pstats.Stats(fn, stream=pout)
+        p.sort_stats('time')
+        p.print_stats()
+        p.print_callers()
+        p.sort_stats('cumulative')
+        p.print_stats()
+
+        pout.flush()
 
 #
 # Was present to work around multiprocessing pool bugs in python < 2.7.3
@@ -1473,14 +1498,20 @@ def edit_bblayers_conf(bblayers_conf, add, remove, edit_cb=None):
 
     return (notadded, notremoved)
 
-
-def get_file_layer(filename, d):
-    """Determine the collection (as defined by a layer's layer.conf file) containing the specified file"""
+def get_collection_res(d):
     collections = (d.getVar('BBFILE_COLLECTIONS') or '').split()
     collection_res = {}
     for collection in collections:
         collection_res[collection] = d.getVar('BBFILE_PATTERN_%s' % collection) or ''
 
+    return collection_res
+
+
+def get_file_layer(filename, d, collection_res={}):
+    """Determine the collection (as defined by a layer's layer.conf file) containing the specified file"""
+    if not collection_res:
+        collection_res = get_collection_res(d)
+
     def path_to_layer(path):
         # Use longest path so we handle nested layers
         matchlen = 0
@@ -1492,12 +1523,13 @@ def get_file_layer(filename, d):
         return match
 
     result = None
-    bbfiles = (d.getVar('BBFILES') or '').split()
+    bbfiles = (d.getVar('BBFILES_PRIORITIZED') or '').split()
     bbfilesmatch = False
     for bbfilesentry in bbfiles:
-        if fnmatch.fnmatch(filename, bbfilesentry):
+        if fnmatch.fnmatchcase(filename, bbfilesentry):
             bbfilesmatch = True
             result = path_to_layer(bbfilesentry)
+            break
 
     if not bbfilesmatch:
         # Probably a bbclass
@@ -1558,8 +1590,8 @@ def set_process_name(name):
     except:
         pass
 
-# export common proxies variables from datastore to environment
 def export_proxies(d):
+    """ export common proxies variables from datastore to environment """
     import os
 
     variables = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY',
@@ -1581,12 +1613,12 @@ def export_proxies(d):
 
 def load_plugins(logger, plugins, pluginpath):
     def load_plugin(name):
-        logger.debug(1, 'Loading plugin %s' % name)
+        logger.debug('Loading plugin %s' % name)
         spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] )
         if spec:
             return spec.loader.load_module()
 
-    logger.debug(1, 'Loading plugins from %s...' % pluginpath)
+    logger.debug('Loading plugins from %s...' % pluginpath)
 
     expanded = (glob.glob(os.path.join(pluginpath, '*' + ext))
                 for ext in python_extensions)
diff --git a/bitbake/lib/bblayers/action.py b/bitbake/lib/bblayers/action.py
index d6459d66..f05f5d33 100644
--- a/bitbake/lib/bblayers/action.py
+++ b/bitbake/lib/bblayers/action.py
@@ -50,10 +50,10 @@ class ActionPlugin(LayerPlugin):
             if not (args.force or notadded):
                 try:
                     self.tinfoil.run_command('parseConfiguration')
-                except bb.tinfoil.TinfoilUIException:
+                except (bb.tinfoil.TinfoilUIException, bb.BBHandledException):
                     # Restore the back up copy of bblayers.conf
                     shutil.copy2(backup, bblayers_conf)
-                    bb.fatal("Parse failure with the specified layer added")
+                    bb.fatal("Parse failure with the specified layer added, aborting.")
                 else:
                     for item in notadded:
                         sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)
@@ -143,11 +143,12 @@ build results (as the layer priority order has effectively changed).
 
         applied_appends = []
         for layer in layers:
-            overlayed = []
-            for f in self.tinfoil.cooker.collection.overlayed.keys():
-                for of in self.tinfoil.cooker.collection.overlayed[f]:
-                    if of.startswith(layer):
-                        overlayed.append(of)
+            overlayed = set()
+            for mc in self.tinfoil.cooker.multiconfigs:
+                for f in self.tinfoil.cooker.collections[mc].overlayed.keys():
+                    for of in self.tinfoil.cooker.collections[mc].overlayed[f]:
+                        if of.startswith(layer):
+                            overlayed.add(of)
 
             logger.plain('Copying files from %s...' % layer )
             for root, dirs, files in os.walk(layer):
@@ -174,14 +175,21 @@ build results (as the layer priority order has effectively changed).
                                     logger.warning('Overwriting file %s', fdest)
                             bb.utils.copyfile(f1full, fdest)
                             if ext == '.bb':
-                                for append in self.tinfoil.cooker.collection.get_file_appends(f1full):
+                                appends = set()
+                                for mc in self.tinfoil.cooker.multiconfigs:
+                                    appends |= set(self.tinfoil.cooker.collections[mc].get_file_appends(f1full))
+                                for append in appends:
                                     if layer_path_match(append):
                                         logger.plain('  Applying append %s to %s' % (append, fdest))
                                         self.apply_append(append, fdest)
                                         applied_appends.append(append)
 
         # Take care of when some layers are excluded and yet we have included bbappends for those recipes
-        for b in self.tinfoil.cooker.collection.bbappends:
+        bbappends = set()
+        for mc in self.tinfoil.cooker.multiconfigs:
+            bbappends |= set(self.tinfoil.cooker.collections[mc].bbappends)
+
+        for b in bbappends:
             (recipename, appendname) = b
             if appendname not in applied_appends:
                 first_append = None
diff --git a/bitbake/lib/bblayers/layerindex.py b/bitbake/lib/bblayers/layerindex.py
index 95b67a66..b2f27b21 100644
--- a/bitbake/lib/bblayers/layerindex.py
+++ b/bitbake/lib/bblayers/layerindex.py
@@ -79,7 +79,7 @@ class LayerIndexPlugin(ActionPlugin):
             branches = [args.branch]
         else:
             branches = (self.tinfoil.config_data.getVar('LAYERSERIES_CORENAMES') or 'master').split()
-        logger.debug(1, 'Trying branches: %s' % branches)
+        logger.debug('Trying branches: %s' % branches)
 
         ignore_layers = []
         if args.ignore:
diff --git a/bitbake/lib/bblayers/query.py b/bitbake/lib/bblayers/query.py
index e2cc3105..947422a7 100644
--- a/bitbake/lib/bblayers/query.py
+++ b/bitbake/lib/bblayers/query.py
@@ -21,6 +21,10 @@ def plugin_init(plugins):
 
 
 class QueryPlugin(LayerPlugin):
+    def __init__(self):
+        super(QueryPlugin, self).__init__()
+        self.collection_res = {}
+
     def do_show_layers(self, args):
         """show current configured layers."""
         logger.plain("%s  %s  %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
@@ -124,7 +128,7 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
                     sys.exit(1)
 
         pkg_pn = self.tinfoil.cooker.recipecaches[mc].pkg_pn
-        (latest_versions, preferred_versions) = self.tinfoil.find_providers(mc)
+        (latest_versions, preferred_versions, required_versions) = self.tinfoil.find_providers(mc)
         allproviders = self.tinfoil.get_all_providers(mc)
 
         # Ensure we list skipped recipes
@@ -222,7 +226,6 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
                             multilayer = True
                         if prov[0] != pref[0]:
                             same_ver = False
-
                     if (multilayer or not show_overlayed_only) and (same_ver or not show_same_ver_only):
                         if not items_listed:
                             logger.plain('=== %s ===' % title)
@@ -243,8 +246,13 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
         else:
             return '?'
 
+    def get_collection_res(self):
+        if not self.collection_res:
+            self.collection_res = bb.utils.get_collection_res(self.tinfoil.config_data)
+        return self.collection_res
+
     def get_file_layerdir(self, filename):
-        layer = bb.utils.get_file_layer(filename, self.tinfoil.config_data)
+        layer = bb.utils.get_file_layer(filename, self.tinfoil.config_data, self.get_collection_res())
         return self.bbfile_collections.get(layer, None)
 
     def remove_layer_prefix(self, f):
@@ -320,12 +328,12 @@ Lists recipes with the bbappends that apply to them as subitems.
     def get_appends_for_files(self, filenames):
         appended, notappended = [], []
         for filename in filenames:
-            _, cls, _ = bb.cache.virtualfn2realfn(filename)
+            _, cls, mc = bb.cache.virtualfn2realfn(filename)
             if cls:
                 continue
 
             basename = os.path.basename(filename)
-            appends = self.tinfoil.cooker.collection.get_file_appends(basename)
+            appends = self.tinfoil.cooker.collections[mc].get_file_appends(basename)
             if appends:
                 appended.append((basename, list(appends)))
             else:
diff --git a/bitbake/lib/bs4/testing.py b/bitbake/lib/bs4/testing.py
index 953bca8e..6584ecf3 100644
--- a/bitbake/lib/bs4/testing.py
+++ b/bitbake/lib/bs4/testing.py
@@ -15,7 +15,7 @@ from bs4.element import (
     SoupStrainer,
 )
 
-from bs4.builder import HTMLParserTreeBuilder
+from bs4.builder._htmlparser import HTMLParserTreeBuilder
 default_builder = HTMLParserTreeBuilder
 
 
@@ -56,7 +56,7 @@ class SoupTest(unittest.TestCase):
                 self.assertEqual(earlier, e.previous_element)
             earlier = e
 
-class HTMLTreeBuilderSmokeTest(object):
+class HTMLTreeBuilderSmokeTest(SoupTest):
 
     """A basic test of a treebuilder's competence.
 
@@ -541,7 +541,7 @@ Hello, world!
         data.a['foo'] = 'bar'
         self.assertEqual('<a foo="bar">text</a>', data.a.decode())
 
-class XMLTreeBuilderSmokeTest(object):
+class XMLTreeBuilderSmokeTest(SoupTest):
 
     def test_pickle_and_unpickle_identity(self):
         # Pickling a tree, then unpickling it, yields a tree identical
diff --git a/bitbake/lib/hashserv/__init__.py b/bitbake/lib/hashserv/__init__.py
index f95e8f43..5f2e101e 100644
--- a/bitbake/lib/hashserv/__init__.py
+++ b/bitbake/lib/hashserv/__init__.py
@@ -3,6 +3,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
+import asyncio
 from contextlib import closing
 import re
 import sqlite3
@@ -21,6 +22,24 @@ ADDR_TYPE_TCP = 1
 # is necessary
 DEFAULT_MAX_CHUNK = 32 * 1024
 
+TABLE_DEFINITION = (
+    ("method", "TEXT NOT NULL"),
+    ("outhash", "TEXT NOT NULL"),
+    ("taskhash", "TEXT NOT NULL"),
+    ("unihash", "TEXT NOT NULL"),
+    ("created", "DATETIME"),
+
+    # Optional fields
+    ("owner", "TEXT"),
+    ("PN", "TEXT"),
+    ("PV", "TEXT"),
+    ("PR", "TEXT"),
+    ("task", "TEXT"),
+    ("outhash_siginfo", "TEXT"),
+)
+
+TABLE_COLUMNS = tuple(name for name, _ in TABLE_DEFINITION)
+
 def setup_database(database, sync=True):
     db = sqlite3.connect(database)
     db.row_factory = sqlite3.Row
@@ -29,23 +48,10 @@ def setup_database(database, sync=True):
         cursor.execute('''
             CREATE TABLE IF NOT EXISTS tasks_v2 (
                 id INTEGER PRIMARY KEY AUTOINCREMENT,
-                method TEXT NOT NULL,
-                outhash TEXT NOT NULL,
-                taskhash TEXT NOT NULL,
-                unihash TEXT NOT NULL,
-                created DATETIME,
-
-                -- Optional fields
-                owner TEXT,
-                PN TEXT,
-                PV TEXT,
-                PR TEXT,
-                task TEXT,
-                outhash_siginfo TEXT,
-
+                %s
                 UNIQUE(method, outhash, taskhash)
                 )
-            ''')
+            ''' % " ".join("%s %s," % (name, typ) for name, typ in TABLE_DEFINITION))
         cursor.execute('PRAGMA journal_mode = WAL')
         cursor.execute('PRAGMA synchronous = %s' % ('NORMAL' if sync else 'OFF'))
 
@@ -88,10 +94,10 @@ def chunkify(msg, max_chunk):
         yield "\n"
 
 
-def create_server(addr, dbname, *, sync=True):
+def create_server(addr, dbname, *, sync=True, upstream=None, read_only=False):
     from . import server
     db = setup_database(dbname, sync=sync)
-    s = server.Server(db)
+    s = server.Server(db, upstream=upstream, read_only=read_only)
 
     (typ, a) = parse_address(addr)
     if typ == ADDR_TYPE_UNIX:
@@ -113,3 +119,15 @@ def create_client(addr):
         c.connect_tcp(*a)
 
     return c
+
+async def create_async_client(addr):
+    from . import client
+    c = client.AsyncClient()
+
+    (typ, a) = parse_address(addr)
+    if typ == ADDR_TYPE_UNIX:
+        await c.connect_unix(*a)
+    else:
+        await c.connect_tcp(*a)
+
+    return c
diff --git a/bitbake/lib/hashserv/client.py b/bitbake/lib/hashserv/client.py
index a29af836..e05c1eb5 100644
--- a/bitbake/lib/hashserv/client.py
+++ b/bitbake/lib/hashserv/client.py
@@ -3,189 +3,231 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
+import asyncio
 import json
 import logging
 import socket
 import os
-from . import chunkify, DEFAULT_MAX_CHUNK
+from . import chunkify, DEFAULT_MAX_CHUNK, create_async_client
 
 
-logger = logging.getLogger('hashserv.client')
+logger = logging.getLogger("hashserv.client")
 
 
 class HashConnectionError(Exception):
     pass
 
 
-class Client(object):
+class AsyncClient(object):
     MODE_NORMAL = 0
     MODE_GET_STREAM = 1
 
     def __init__(self):
-        self._socket = None
         self.reader = None
         self.writer = None
         self.mode = self.MODE_NORMAL
         self.max_chunk = DEFAULT_MAX_CHUNK
 
-    def connect_tcp(self, address, port):
-        def connect_sock():
-            s = socket.create_connection((address, port))
-
-            s.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)
-            s.setsockopt(socket.SOL_TCP, socket.TCP_QUICKACK, 1)
-            s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
-            return s
+    async def connect_tcp(self, address, port):
+        async def connect_sock():
+            return await asyncio.open_connection(address, port)
 
         self._connect_sock = connect_sock
 
-    def connect_unix(self, path):
-        def connect_sock():
-            s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-            # AF_UNIX has path length issues so chdir here to workaround
-            cwd = os.getcwd()
-            try:
-                os.chdir(os.path.dirname(path))
-                s.connect(os.path.basename(path))
-            finally:
-                os.chdir(cwd)
-            return s
+    async def connect_unix(self, path):
+        async def connect_sock():
+            return await asyncio.open_unix_connection(path)
 
         self._connect_sock = connect_sock
 
-    def connect(self):
-        if self._socket is None:
-            self._socket = self._connect_sock()
-
-            self.reader = self._socket.makefile('r', encoding='utf-8')
-            self.writer = self._socket.makefile('w', encoding='utf-8')
+    async def connect(self):
+        if self.reader is None or self.writer is None:
+            (self.reader, self.writer) = await self._connect_sock()
 
-            self.writer.write('OEHASHEQUIV 1.1\n\n')
-            self.writer.flush()
+            self.writer.write("OEHASHEQUIV 1.1\n\n".encode("utf-8"))
+            await self.writer.drain()
 
-            # Restore mode if the socket is being re-created
             cur_mode = self.mode
             self.mode = self.MODE_NORMAL
-            self._set_mode(cur_mode)
+            await self._set_mode(cur_mode)
 
-        return self._socket
+    async def close(self):
+        self.reader = None
 
-    def close(self):
-        if self._socket is not None:
-            self._socket.close()
-            self._socket = None
-            self.reader = None
+        if self.writer is not None:
+            self.writer.close()
             self.writer = None
 
-    def _send_wrapper(self, proc):
+    async def _send_wrapper(self, proc):
         count = 0
         while True:
             try:
-                self.connect()
-                return proc()
-            except (OSError, HashConnectionError, json.JSONDecodeError, UnicodeDecodeError) as e:
-                logger.warning('Error talking to server: %s' % e)
+                await self.connect()
+                return await proc()
+            except (
+                OSError,
+                HashConnectionError,
+                json.JSONDecodeError,
+                UnicodeDecodeError,
+            ) as e:
+                logger.warning("Error talking to server: %s" % e)
                 if count >= 3:
                     if not isinstance(e, HashConnectionError):
                         raise HashConnectionError(str(e))
                     raise e
-                self.close()
+                await self.close()
                 count += 1
 
-    def send_message(self, msg):
-        def get_line():
-            line = self.reader.readline()
+    async def send_message(self, msg):
+        async def get_line():
+            line = await self.reader.readline()
             if not line:
-                raise HashConnectionError('Connection closed')
+                raise HashConnectionError("Connection closed")
+
+            line = line.decode("utf-8")
 
-            if not line.endswith('\n'):
-                raise HashConnectionError('Bad message %r' % message)
+            if not line.endswith("\n"):
+                raise HashConnectionError("Bad message %r" % message)
 
             return line
 
-        def proc():
+        async def proc():
             for c in chunkify(json.dumps(msg), self.max_chunk):
-                self.writer.write(c)
-            self.writer.flush()
+                self.writer.write(c.encode("utf-8"))
+            await self.writer.drain()
 
-            l = get_line()
+            l = await get_line()
 
             m = json.loads(l)
-            if 'chunk-stream' in m:
+            if m and "chunk-stream" in m:
                 lines = []
                 while True:
-                    l = get_line().rstrip('\n')
+                    l = (await get_line()).rstrip("\n")
                     if not l:
                         break
                     lines.append(l)
 
-                m = json.loads(''.join(lines))
+                m = json.loads("".join(lines))
 
             return m
 
-        return self._send_wrapper(proc)
+        return await self._send_wrapper(proc)
 
-    def send_stream(self, msg):
-        def proc():
-            self.writer.write("%s\n" % msg)
-            self.writer.flush()
-            l = self.reader.readline()
+    async def send_stream(self, msg):
+        async def proc():
+            self.writer.write(("%s\n" % msg).encode("utf-8"))
+            await self.writer.drain()
+            l = await self.reader.readline()
             if not l:
-                raise HashConnectionError('Connection closed')
-            return l.rstrip()
+                raise HashConnectionError("Connection closed")
+            return l.decode("utf-8").rstrip()
 
-        return self._send_wrapper(proc)
+        return await self._send_wrapper(proc)
 
-    def _set_mode(self, new_mode):
+    async def _set_mode(self, new_mode):
         if new_mode == self.MODE_NORMAL and self.mode == self.MODE_GET_STREAM:
-            r = self.send_stream('END')
-            if r != 'ok':
-                raise HashConnectionError('Bad response from server %r' % r)
+            r = await self.send_stream("END")
+            if r != "ok":
+                raise HashConnectionError("Bad response from server %r" % r)
         elif new_mode == self.MODE_GET_STREAM and self.mode == self.MODE_NORMAL:
-            r = self.send_message({'get-stream': None})
-            if r != 'ok':
-                raise HashConnectionError('Bad response from server %r' % r)
+            r = await self.send_message({"get-stream": None})
+            if r != "ok":
+                raise HashConnectionError("Bad response from server %r" % r)
         elif new_mode != self.mode:
-            raise Exception('Undefined mode transition %r -> %r' % (self.mode, new_mode))
+            raise Exception(
+                "Undefined mode transition %r -> %r" % (self.mode, new_mode)
+            )
 
         self.mode = new_mode
 
-    def get_unihash(self, method, taskhash):
-        self._set_mode(self.MODE_GET_STREAM)
-        r = self.send_stream('%s %s' % (method, taskhash))
+    async def get_unihash(self, method, taskhash):
+        await self._set_mode(self.MODE_GET_STREAM)
+        r = await self.send_stream("%s %s" % (method, taskhash))
         if not r:
             return None
         return r
 
-    def report_unihash(self, taskhash, method, outhash, unihash, extra={}):
-        self._set_mode(self.MODE_NORMAL)
+    async def report_unihash(self, taskhash, method, outhash, unihash, extra={}):
+        await self._set_mode(self.MODE_NORMAL)
         m = extra.copy()
-        m['taskhash'] = taskhash
-        m['method'] = method
-        m['outhash'] = outhash
-        m['unihash'] = unihash
-        return self.send_message({'report': m})
-
-    def report_unihash_equiv(self, taskhash, method, unihash, extra={}):
-        self._set_mode(self.MODE_NORMAL)
+        m["taskhash"] = taskhash
+        m["method"] = method
+        m["outhash"] = outhash
+        m["unihash"] = unihash
+        return await self.send_message({"report": m})
+
+    async def report_unihash_equiv(self, taskhash, method, unihash, extra={}):
+        await self._set_mode(self.MODE_NORMAL)
         m = extra.copy()
-        m['taskhash'] = taskhash
-        m['method'] = method
-        m['unihash'] = unihash
-        return self.send_message({'report-equiv': m})
-
-    def get_taskhash(self, method, taskhash, all_properties=False):
-        self._set_mode(self.MODE_NORMAL)
-        return self.send_message({'get': {
-            'taskhash': taskhash,
-            'method': method,
-            'all': all_properties
-        }})
-
-    def get_stats(self):
-        self._set_mode(self.MODE_NORMAL)
-        return self.send_message({'get-stats': None})
-
-    def reset_stats(self):
-        self._set_mode(self.MODE_NORMAL)
-        return self.send_message({'reset-stats': None})
+        m["taskhash"] = taskhash
+        m["method"] = method
+        m["unihash"] = unihash
+        return await self.send_message({"report-equiv": m})
+
+    async def get_taskhash(self, method, taskhash, all_properties=False):
+        await self._set_mode(self.MODE_NORMAL)
+        return await self.send_message(
+            {"get": {"taskhash": taskhash, "method": method, "all": all_properties}}
+        )
+
+    async def get_outhash(self, method, outhash, taskhash):
+        await self._set_mode(self.MODE_NORMAL)
+        return await self.send_message(
+            {"get-outhash": {"outhash": outhash, "taskhash": taskhash, "method": method}}
+        )
+
+    async def get_stats(self):
+        await self._set_mode(self.MODE_NORMAL)
+        return await self.send_message({"get-stats": None})
+
+    async def reset_stats(self):
+        await self._set_mode(self.MODE_NORMAL)
+        return await self.send_message({"reset-stats": None})
+
+    async def backfill_wait(self):
+        await self._set_mode(self.MODE_NORMAL)
+        return (await self.send_message({"backfill-wait": None}))["tasks"]
+
+
+class Client(object):
+    def __init__(self):
+        self.client = AsyncClient()
+        self.loop = asyncio.new_event_loop()
+
+        for call in (
+            "connect_tcp",
+            "close",
+            "get_unihash",
+            "report_unihash",
+            "report_unihash_equiv",
+            "get_taskhash",
+            "get_stats",
+            "reset_stats",
+            "backfill_wait",
+        ):
+            downcall = getattr(self.client, call)
+            setattr(self, call, self._get_downcall_wrapper(downcall))
+
+    def _get_downcall_wrapper(self, downcall):
+        def wrapper(*args, **kwargs):
+            return self.loop.run_until_complete(downcall(*args, **kwargs))
+
+        return wrapper
+
+    def connect_unix(self, path):
+        # AF_UNIX has path length issues so chdir here to workaround
+        cwd = os.getcwd()
+        try:
+            os.chdir(os.path.dirname(path))
+            self.loop.run_until_complete(self.client.connect_unix(os.path.basename(path)))
+            self.loop.run_until_complete(self.client.connect())
+        finally:
+            os.chdir(cwd)
+
+    @property
+    def max_chunk(self):
+        return self.client.max_chunk
+
+    @max_chunk.setter
+    def max_chunk(self, value):
+        self.client.max_chunk = value
diff --git a/bitbake/lib/hashserv/server.py b/bitbake/lib/hashserv/server.py
index 81050715..a0dc0c17 100644
--- a/bitbake/lib/hashserv/server.py
+++ b/bitbake/lib/hashserv/server.py
@@ -3,7 +3,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
 
-from contextlib import closing
+from contextlib import closing, contextmanager
 from datetime import datetime
 import asyncio
 import json
@@ -12,8 +12,9 @@ import math
 import os
 import signal
 import socket
+import sys
 import time
-from . import chunkify, DEFAULT_MAX_CHUNK
+from . import chunkify, DEFAULT_MAX_CHUNK, create_async_client, TABLE_COLUMNS
 
 logger = logging.getLogger('hashserv.server')
 
@@ -111,29 +112,95 @@ class Stats(object):
 class ClientError(Exception):
     pass
 
+class ServerError(Exception):
+    pass
+
+def insert_task(cursor, data, ignore=False):
+    keys = sorted(data.keys())
+    query = '''INSERT%s INTO tasks_v2 (%s) VALUES (%s)''' % (
+        " OR IGNORE" if ignore else "",
+        ', '.join(keys),
+        ', '.join(':' + k for k in keys))
+    cursor.execute(query, data)
+
+async def copy_from_upstream(client, db, method, taskhash):
+    d = await client.get_taskhash(method, taskhash, True)
+    if d is not None:
+        # Filter out unknown columns
+        d = {k: v for k, v in d.items() if k in TABLE_COLUMNS}
+        keys = sorted(d.keys())
+
+        with closing(db.cursor()) as cursor:
+            insert_task(cursor, d)
+            db.commit()
+
+    return d
+
+async def copy_outhash_from_upstream(client, db, method, outhash, taskhash):
+    d = await client.get_outhash(method, outhash, taskhash)
+    if d is not None:
+        # Filter out unknown columns
+        d = {k: v for k, v in d.items() if k in TABLE_COLUMNS}
+        keys = sorted(d.keys())
+
+        with closing(db.cursor()) as cursor:
+            insert_task(cursor, d)
+            db.commit()
+
+    return d
+
 class ServerClient(object):
     FAST_QUERY = 'SELECT taskhash, method, unihash FROM tasks_v2 WHERE method=:method AND taskhash=:taskhash ORDER BY created ASC LIMIT 1'
     ALL_QUERY =  'SELECT *                         FROM tasks_v2 WHERE method=:method AND taskhash=:taskhash ORDER BY created ASC LIMIT 1'
-
-    def __init__(self, reader, writer, db, request_stats):
+    OUTHASH_QUERY = '''
+        -- Find tasks with a matching outhash (that is, tasks that
+        -- are equivalent)
+        SELECT * FROM tasks_v2 WHERE method=:method AND outhash=:outhash
+
+        -- If there is an exact match on the taskhash, return it.
+        -- Otherwise return the oldest matching outhash of any
+        -- taskhash
+        ORDER BY CASE WHEN taskhash=:taskhash THEN 1 ELSE 2 END,
+            created ASC
+
+        -- Only return one row
+        LIMIT 1
+        '''
+
+    def __init__(self, reader, writer, db, request_stats, backfill_queue, upstream, read_only):
         self.reader = reader
         self.writer = writer
         self.db = db
         self.request_stats = request_stats
         self.max_chunk = DEFAULT_MAX_CHUNK
+        self.backfill_queue = backfill_queue
+        self.upstream = upstream
 
         self.handlers = {
             'get': self.handle_get,
-            'report': self.handle_report,
-            'report-equiv': self.handle_equivreport,
+            'get-outhash': self.handle_get_outhash,
             'get-stream': self.handle_get_stream,
             'get-stats': self.handle_get_stats,
-            'reset-stats': self.handle_reset_stats,
             'chunk-stream': self.handle_chunk,
         }
 
+        if not read_only:
+            self.handlers.update({
+                'report': self.handle_report,
+                'report-equiv': self.handle_equivreport,
+                'reset-stats': self.handle_reset_stats,
+                'backfill-wait': self.handle_backfill_wait,
+            })
+
     async def process_requests(self):
+        if self.upstream is not None:
+            self.upstream_client = await create_async_client(self.upstream)
+        else:
+            self.upstream_client = None
+
         try:
+
+
             self.addr = self.writer.get_extra_info('peername')
             logger.debug('Client %r connected' % (self.addr,))
 
@@ -171,6 +238,9 @@ class ServerClient(object):
         except ClientError as e:
             logger.error(str(e))
         finally:
+            if self.upstream_client is not None:
+                await self.upstream_client.close()
+
             self.writer.close()
 
     async def dispatch_message(self, msg):
@@ -239,15 +309,34 @@ class ServerClient(object):
         if row is not None:
             logger.debug('Found equivalent task %s -> %s', (row['taskhash'], row['unihash']))
             d = {k: row[k] for k in row.keys()}
+        elif self.upstream_client is not None:
+            d = await copy_from_upstream(self.upstream_client, self.db, method, taskhash)
+        else:
+            d = None
 
-            self.write_message(d)
+        self.write_message(d)
+
+    async def handle_get_outhash(self, request):
+        with closing(self.db.cursor()) as cursor:
+            cursor.execute(self.OUTHASH_QUERY,
+                           {k: request[k] for k in ('method', 'outhash', 'taskhash')})
+
+            row = cursor.fetchone()
+
+        if row is not None:
+            logger.debug('Found equivalent outhash %s -> %s', (row['outhash'], row['unihash']))
+            d = {k: row[k] for k in row.keys()}
         else:
-            self.write_message(None)
+            d = None
+
+        self.write_message(d)
 
     async def handle_get_stream(self, request):
         self.write_message('ok')
 
         while True:
+            upstream = None
+
             l = await self.reader.readline()
             if not l:
                 return
@@ -272,6 +361,12 @@ class ServerClient(object):
                 if row is not None:
                     msg = ('%s\n' % row['unihash']).encode('utf-8')
                     #logger.debug('Found equivalent task %s -> %s', (row['taskhash'], row['unihash']))
+                elif self.upstream_client is not None:
+                    upstream = await self.upstream_client.get_unihash(method, taskhash)
+                    if upstream:
+                        msg = ("%s\n" % upstream).encode("utf-8")
+                    else:
+                        msg = "\n".encode("utf-8")
                 else:
                     msg = '\n'.encode('utf-8')
 
@@ -282,25 +377,26 @@ class ServerClient(object):
 
             await self.writer.drain()
 
+            # Post to the backfill queue after writing the result to minimize
+            # the turn around time on a request
+            if upstream is not None:
+                await self.backfill_queue.put((method, taskhash))
+
     async def handle_report(self, data):
         with closing(self.db.cursor()) as cursor:
-            cursor.execute('''
-                -- Find tasks with a matching outhash (that is, tasks that
-                -- are equivalent)
-                SELECT taskhash, method, unihash FROM tasks_v2 WHERE method=:method AND outhash=:outhash
-
-                -- If there is an exact match on the taskhash, return it.
-                -- Otherwise return the oldest matching outhash of any
-                -- taskhash
-                ORDER BY CASE WHEN taskhash=:taskhash THEN 1 ELSE 2 END,
-                    created ASC
-
-                -- Only return one row
-                LIMIT 1
-                ''', {k: data[k] for k in ('method', 'outhash', 'taskhash')})
+            cursor.execute(self.OUTHASH_QUERY,
+                           {k: data[k] for k in ('method', 'outhash', 'taskhash')})
 
             row = cursor.fetchone()
 
+            if row is None and self.upstream_client:
+                # Try upstream
+                row = await copy_outhash_from_upstream(self.upstream_client,
+                                                       self.db,
+                                                       data['method'],
+                                                       data['outhash'],
+                                                       data['taskhash'])
+
             # If no matching outhash was found, or one *was* found but it
             # wasn't an exact match on the taskhash, a new entry for this
             # taskhash should be added
@@ -324,11 +420,7 @@ class ServerClient(object):
                     if k in data:
                         insert_data[k] = data[k]
 
-                cursor.execute('''INSERT INTO tasks_v2 (%s) VALUES (%s)''' % (
-                    ', '.join(sorted(insert_data.keys())),
-                    ', '.join(':' + k for k in sorted(insert_data.keys()))),
-                    insert_data)
-
+                insert_task(cursor, insert_data)
                 self.db.commit()
 
                 logger.info('Adding taskhash %s with unihash %s',
@@ -358,11 +450,7 @@ class ServerClient(object):
                 if k in data:
                     insert_data[k] = data[k]
 
-            cursor.execute('''INSERT OR IGNORE INTO tasks_v2 (%s) VALUES (%s)''' % (
-                ', '.join(sorted(insert_data.keys())),
-                ', '.join(':' + k for k in sorted(insert_data.keys()))),
-                insert_data)
-
+            insert_task(cursor, insert_data, ignore=True)
             self.db.commit()
 
             # Fetch the unihash that will be reported for the taskhash. If the
@@ -394,6 +482,13 @@ class ServerClient(object):
         self.request_stats.reset()
         self.write_message(d)
 
+    async def handle_backfill_wait(self, request):
+        d = {
+            'tasks': self.backfill_queue.qsize(),
+        }
+        await self.backfill_queue.join()
+        self.write_message(d)
+
     def query_equivalent(self, method, taskhash, query):
         # This is part of the inner loop and must be as fast as possible
         try:
@@ -405,7 +500,10 @@ class ServerClient(object):
 
 
 class Server(object):
-    def __init__(self, db, loop=None):
+    def __init__(self, db, loop=None, upstream=None, read_only=False):
+        if upstream and read_only:
+            raise ServerError("Read-only hashserv cannot pull from an upstream server")
+
         self.request_stats = Stats()
         self.db = db
 
@@ -416,6 +514,9 @@ class Server(object):
             self.loop = loop
             self.close_loop = False
 
+        self.upstream = upstream
+        self.read_only = read_only
+
         self._cleanup_socket = None
 
     def start_tcp_server(self, host, port):
@@ -458,7 +559,7 @@ class Server(object):
     async def handle_client(self, reader, writer):
         # writer.transport.set_write_buffer_limits(0)
         try:
-            client = ServerClient(reader, writer, self.db, self.request_stats)
+            client = ServerClient(reader, writer, self.db, self.request_stats, self.backfill_queue, self.upstream, self.read_only)
             await client.process_requests()
         except Exception as e:
             import traceback
@@ -467,23 +568,60 @@ class Server(object):
             writer.close()
         logger.info('Client disconnected')
 
+    @contextmanager
+    def _backfill_worker(self):
+        async def backfill_worker_task():
+            client = await create_async_client(self.upstream)
+            try:
+                while True:
+                    item = await self.backfill_queue.get()
+                    if item is None:
+                        self.backfill_queue.task_done()
+                        break
+                    method, taskhash = item
+                    await copy_from_upstream(client, self.db, method, taskhash)
+                    self.backfill_queue.task_done()
+            finally:
+                await client.close()
+
+        async def join_worker(worker):
+            await self.backfill_queue.put(None)
+            await worker
+
+        if self.upstream is not None:
+            worker = asyncio.ensure_future(backfill_worker_task())
+            try:
+                yield
+            finally:
+                self.loop.run_until_complete(join_worker(worker))
+        else:
+            yield
+
     def serve_forever(self):
         def signal_handler():
             self.loop.stop()
 
-        self.loop.add_signal_handler(signal.SIGTERM, signal_handler)
-
+        asyncio.set_event_loop(self.loop)
         try:
-            self.loop.run_forever()
-        except KeyboardInterrupt:
-            pass
+            self.backfill_queue = asyncio.Queue()
 
-        self.server.close()
-        self.loop.run_until_complete(self.server.wait_closed())
-        logger.info('Server shutting down')
+            self.loop.add_signal_handler(signal.SIGTERM, signal_handler)
 
-        if self.close_loop:
-            self.loop.close()
+            with self._backfill_worker():
+                try:
+                    self.loop.run_forever()
+                except KeyboardInterrupt:
+                    pass
+
+                self.server.close()
+
+            self.loop.run_until_complete(self.server.wait_closed())
+            logger.info('Server shutting down')
+        finally:
+            if self.close_loop:
+                if sys.version_info >= (3, 6):
+                    self.loop.run_until_complete(self.loop.shutdown_asyncgens())
+                self.loop.close()
 
-        if self._cleanup_socket is not None:
-            self._cleanup_socket()
+            if self._cleanup_socket is not None:
+                self._cleanup_socket()
diff --git a/bitbake/lib/hashserv/tests.py b/bitbake/lib/hashserv/tests.py
index 6e862950..1a696481 100644
--- a/bitbake/lib/hashserv/tests.py
+++ b/bitbake/lib/hashserv/tests.py
@@ -6,52 +6,79 @@
 #
 
 from . import create_server, create_client
+from .client import HashConnectionError
 import hashlib
 import logging
 import multiprocessing
+import os
 import sys
 import tempfile
 import threading
 import unittest
+import socket
 
+def _run_server(server, idx):
+    # logging.basicConfig(level=logging.DEBUG, filename='bbhashserv.log', filemode='w',
+    #                     format='%(levelname)s %(filename)s:%(lineno)d %(message)s')
+    sys.stdout = open('bbhashserv-%d.log' % idx, 'w')
+    sys.stderr = sys.stdout
+    server.serve_forever()
 
-class TestHashEquivalenceServer(object):
+
+class HashEquivalenceTestSetup(object):
     METHOD = 'TestMethod'
 
-    def _run_server(self):
-        # logging.basicConfig(level=logging.DEBUG, filename='bbhashserv.log', filemode='w',
-        #                     format='%(levelname)s %(filename)s:%(lineno)d %(message)s')
-        self.server.serve_forever()
+    server_index = 0
+
+    def start_server(self, dbpath=None, upstream=None, read_only=False):
+        self.server_index += 1
+        if dbpath is None:
+            dbpath = os.path.join(self.temp_dir.name, "db%d.sqlite" % self.server_index)
+
+        def cleanup_thread(thread):
+            thread.terminate()
+            thread.join()
+
+        server = create_server(self.get_server_addr(self.server_index),
+                               dbpath,
+                               upstream=upstream,
+                               read_only=read_only)
+        server.dbpath = dbpath
+
+        server.thread = multiprocessing.Process(target=_run_server, args=(server, self.server_index))
+        server.thread.start()
+        self.addCleanup(cleanup_thread, server.thread)
+
+        def cleanup_client(client):
+            client.close()
+
+        client = create_client(server.address)
+        self.addCleanup(cleanup_client, client)
+
+        return (client, server)
 
     def setUp(self):
         if sys.version_info < (3, 5, 0):
             self.skipTest('Python 3.5 or later required')
 
         self.temp_dir = tempfile.TemporaryDirectory(prefix='bb-hashserv')
-        self.dbfile = os.path.join(self.temp_dir.name, 'db.sqlite')
-
-        self.server = create_server(self.get_server_addr(), self.dbfile)
-        self.server_thread = multiprocessing.Process(target=self._run_server)
-        self.server_thread.start()
-        self.client = create_client(self.server.address)
-
-    def tearDown(self):
-        # Shutdown server
-        s = getattr(self, 'server', None)
-        if s is not None:
-            self.server_thread.terminate()
-            self.server_thread.join()
-        self.client.close()
-        self.temp_dir.cleanup()
+        self.addCleanup(self.temp_dir.cleanup)
+
+        (self.client, self.server) = self.start_server()
+
+    def assertClientGetHash(self, client, taskhash, unihash):
+        result = client.get_unihash(self.METHOD, taskhash)
+        self.assertEqual(result, unihash)
 
+
+class HashEquivalenceCommonTests(object):
     def test_create_hash(self):
         # Simple test that hashes can be created
         taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9'
         outhash = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f'
         unihash = 'f46d3fbb439bd9b921095da657a4de906510d2cd'
 
-        result = self.client.get_unihash(self.METHOD, taskhash)
-        self.assertIsNone(result, msg='Found unexpected task, %r' % result)
+        self.assertClientGetHash(self.client, taskhash, None)
 
         result = self.client.report_unihash(taskhash, self.METHOD, outhash, unihash)
         self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash')
@@ -82,22 +109,19 @@ class TestHashEquivalenceServer(object):
         unihash = '218e57509998197d570e2c98512d0105985dffc9'
         self.client.report_unihash(taskhash, self.METHOD, outhash, unihash)
 
-        result = self.client.get_unihash(self.METHOD, taskhash)
-        self.assertEqual(result, unihash)
+        self.assertClientGetHash(self.client, taskhash, unihash)
 
         outhash2 = '0904a7fe3dc712d9fd8a74a616ddca2a825a8ee97adf0bd3fc86082c7639914d'
         unihash2 = 'ae9a7d252735f0dafcdb10e2e02561ca3a47314c'
         self.client.report_unihash(taskhash, self.METHOD, outhash2, unihash2)
 
-        result = self.client.get_unihash(self.METHOD, taskhash)
-        self.assertEqual(result, unihash)
+        self.assertClientGetHash(self.client, taskhash, unihash)
 
         outhash3 = '77623a549b5b1a31e3732dfa8fe61d7ce5d44b3370f253c5360e136b852967b4'
         unihash3 = '9217a7d6398518e5dc002ed58f2cbbbc78696603'
         self.client.report_unihash(taskhash, self.METHOD, outhash3, unihash3)
 
-        result = self.client.get_unihash(self.METHOD, taskhash)
-        self.assertEqual(result, unihash)
+        self.assertClientGetHash(self.client, taskhash, unihash)
 
     def test_huge_message(self):
         # Simple test that hashes can be created
@@ -105,8 +129,7 @@ class TestHashEquivalenceServer(object):
         outhash = '3c979c3db45c569f51ab7626a4651074be3a9d11a84b1db076f5b14f7d39db44'
         unihash = '90e9bc1d1f094c51824adca7f8ea79a048d68824'
 
-        result = self.client.get_unihash(self.METHOD, taskhash)
-        self.assertIsNone(result, msg='Found unexpected task, %r' % result)
+        self.assertClientGetHash(self.client, taskhash, None)
 
         siginfo = "0" * (self.client.max_chunk * 4)
 
@@ -154,12 +177,140 @@ class TestHashEquivalenceServer(object):
 
         self.assertFalse(failures)
 
+    def test_upstream_server(self):
+        # Tests upstream server support. This is done by creating two servers
+        # that share a database file. The downstream server has it upstream
+        # set to the test server, whereas the side server doesn't. This allows
+        # verification that the hash requests are being proxied to the upstream
+        # server by verifying that they appear on the downstream client, but not
+        # the side client. It also verifies that the results are pulled into
+        # the downstream database by checking that the downstream and side servers
+        # match after the downstream is done waiting for all backfill tasks
+        (down_client, down_server) = self.start_server(upstream=self.server.address)
+        (side_client, side_server) = self.start_server(dbpath=down_server.dbpath)
+
+        def check_hash(taskhash, unihash, old_sidehash):
+            nonlocal down_client
+            nonlocal side_client
+
+            # check upstream server
+            self.assertClientGetHash(self.client, taskhash, unihash)
+
+            # Hash should *not* be present on the side server
+            self.assertClientGetHash(side_client, taskhash, old_sidehash)
+
+            # Hash should be present on the downstream server, since it
+            # will defer to the upstream server. This will trigger
+            # the backfill in the downstream server
+            self.assertClientGetHash(down_client, taskhash, unihash)
+
+            # After waiting for the downstream client to finish backfilling the
+            # task from the upstream server, it should appear in the side server
+            # since the database is populated
+            down_client.backfill_wait()
+            self.assertClientGetHash(side_client, taskhash, unihash)
+
+        # Basic report
+        taskhash = '8aa96fcffb5831b3c2c0cb75f0431e3f8b20554a'
+        outhash = 'afe240a439959ce86f5e322f8c208e1fedefea9e813f2140c81af866cc9edf7e'
+        unihash = '218e57509998197d570e2c98512d0105985dffc9'
+        self.client.report_unihash(taskhash, self.METHOD, outhash, unihash)
+
+        check_hash(taskhash, unihash, None)
+
+        # Duplicated taskhash with multiple output hashes and unihashes.
+        # All servers should agree with the originally reported hash
+        outhash2 = '0904a7fe3dc712d9fd8a74a616ddca2a825a8ee97adf0bd3fc86082c7639914d'
+        unihash2 = 'ae9a7d252735f0dafcdb10e2e02561ca3a47314c'
+        self.client.report_unihash(taskhash, self.METHOD, outhash2, unihash2)
+
+        check_hash(taskhash, unihash, unihash)
+
+        # Report an equivalent task. The sideload will originally report
+        # no unihash until backfilled
+        taskhash3 = "044c2ec8aaf480685a00ff6ff49e6162e6ad34e1"
+        unihash3 = "def64766090d28f627e816454ed46894bb3aab36"
+        self.client.report_unihash(taskhash3, self.METHOD, outhash, unihash3)
+
+        check_hash(taskhash3, unihash, None)
+
+        # Test that reporting a unihash in the downstream client isn't
+        # propagating to the upstream server
+        taskhash4 = "e3da00593d6a7fb435c7e2114976c59c5fd6d561"
+        outhash4 = "1cf8713e645f491eb9c959d20b5cae1c47133a292626dda9b10709857cbe688a"
+        unihash4 = "3b5d3d83f07f259e9086fcb422c855286e18a57d"
+        down_client.report_unihash(taskhash4, self.METHOD, outhash4, unihash4)
+        down_client.backfill_wait()
 
-class TestHashEquivalenceUnixServer(TestHashEquivalenceServer, unittest.TestCase):
-    def get_server_addr(self):
-        return "unix://" + os.path.join(self.temp_dir.name, 'sock')
+        self.assertClientGetHash(down_client, taskhash4, unihash4)
+        self.assertClientGetHash(side_client, taskhash4, unihash4)
+        self.assertClientGetHash(self.client, taskhash4, None)
+
+        # Test that reporting a unihash in the downstream is able to find a
+        # match which was previously reported to the upstream server
+        taskhash5 = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9'
+        outhash5 = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f'
+        unihash5 = 'f46d3fbb439bd9b921095da657a4de906510d2cd'
+        result = self.client.report_unihash(taskhash5, self.METHOD, outhash5, unihash5)
+
+        taskhash6 = '35788efcb8dfb0a02659d81cf2bfd695fb30fafa'
+        unihash6 = 'f46d3fbb439bd9b921095da657a4de906510d2ce'
+        result = down_client.report_unihash(taskhash6, self.METHOD, outhash5, unihash6)
+        self.assertEqual(result['unihash'], unihash5, 'Server failed to copy unihash from upstream')
+
+    def test_ro_server(self):
+        (ro_client, ro_server) = self.start_server(dbpath=self.server.dbpath, read_only=True)
+
+        # Report a hash via the read-write server
+        taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9'
+        outhash = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f'
+        unihash = 'f46d3fbb439bd9b921095da657a4de906510d2cd'
+
+        result = self.client.report_unihash(taskhash, self.METHOD, outhash, unihash)
+        self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash')
+
+        # Check the hash via the read-only server
+        self.assertClientGetHash(ro_client, taskhash, unihash)
+
+        # Ensure that reporting via the read-only server fails
+        taskhash2 = 'c665584ee6817aa99edfc77a44dd853828279370'
+        outhash2 = '3c979c3db45c569f51ab7626a4651074be3a9d11a84b1db076f5b14f7d39db44'
+        unihash2 = '90e9bc1d1f094c51824adca7f8ea79a048d68824'
+
+        with self.assertRaises(HashConnectionError):
+            ro_client.report_unihash(taskhash2, self.METHOD, outhash2, unihash2)
+
+        # Ensure that the database was not modified
+        self.assertClientGetHash(self.client, taskhash2, None)
+
+
+class TestHashEquivalenceUnixServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase):
+    def get_server_addr(self, server_idx):
+        return "unix://" + os.path.join(self.temp_dir.name, 'sock%d' % server_idx)
+
+
+class TestHashEquivalenceUnixServerLongPath(HashEquivalenceTestSetup, unittest.TestCase):
+    DEEP_DIRECTORY = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccccccccccccccccccccccccccccccccccccc"
+    def get_server_addr(self, server_idx):
+        os.makedirs(os.path.join(self.temp_dir.name, self.DEEP_DIRECTORY), exist_ok=True)
+        return "unix://" + os.path.join(self.temp_dir.name, self.DEEP_DIRECTORY, 'sock%d' % server_idx)
+
+
+    def test_long_sock_path(self):
+        # Simple test that hashes can be created
+        taskhash = '35788efcb8dfb0a02659d81cf2bfd695fb30faf9'
+        outhash = '2765d4a5884be49b28601445c2760c5f21e7e5c0ee2b7e3fce98fd7e5970796f'
+        unihash = 'f46d3fbb439bd9b921095da657a4de906510d2cd'
+
+        self.assertClientGetHash(self.client, taskhash, None)
+
+        result = self.client.report_unihash(taskhash, self.METHOD, outhash, unihash)
+        self.assertEqual(result['unihash'], unihash, 'Server returned bad unihash')
 
 
-class TestHashEquivalenceTCPServer(TestHashEquivalenceServer, unittest.TestCase):
-    def get_server_addr(self):
-        return "localhost:0"
+class TestHashEquivalenceTCPServer(HashEquivalenceTestSetup, HashEquivalenceCommonTests, unittest.TestCase):
+    def get_server_addr(self, server_idx):
+        # Some hosts cause asyncio module to misbehave, when IPv6 is not enabled.
+        # If IPv6 is enabled, it should be safe to use localhost directly, in general
+        # case it is more reliable to resolve the IP address explicitly.
+        return socket.gethostbyname("localhost") + ":0"
diff --git a/bitbake/lib/layerindexlib/__init__.py b/bitbake/lib/layerindexlib/__init__.py
index 77196b40..9ca127b9 100644
--- a/bitbake/lib/layerindexlib/__init__.py
+++ b/bitbake/lib/layerindexlib/__init__.py
@@ -7,6 +7,7 @@ import datetime
 
 import logging
 import imp
+import os
 
 from collections import OrderedDict
 from layerindexlib.plugin import LayerIndexPluginUrlError
@@ -70,7 +71,7 @@ class LayerIndex():
 
         if self.__class__ != newIndex.__class__ or \
            other.__class__ != newIndex.__class__:
-            raise TypeException("Can not add different types.")
+            raise TypeError("Can not add different types.")
 
         for indexEnt in self.indexes:
             newIndex.indexes.append(indexEnt)
@@ -93,7 +94,7 @@ class LayerIndex():
            if not param:
                continue
            item = param.split('=', 1)
-           logger.debug(1, item)
+           logger.debug(item)
            param_dict[item[0]] = item[1]
 
         return param_dict
@@ -122,7 +123,7 @@ class LayerIndex():
         up = urlparse(url)
 
         if username:
-            logger.debug(1, "Configuring authentication for %s..." % url)
+            logger.debug("Configuring authentication for %s..." % url)
             password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
             password_mgr.add_password(None, "%s://%s" % (up.scheme, up.netloc), username, password)
             handler = urllib.request.HTTPBasicAuthHandler(password_mgr)
@@ -132,20 +133,20 @@ class LayerIndex():
 
         urllib.request.install_opener(opener)
 
-        logger.debug(1, "Fetching %s (%s)..." % (url, ["without authentication", "with authentication"][bool(username)]))
+        logger.debug("Fetching %s (%s)..." % (url, ["without authentication", "with authentication"][bool(username)]))
 
         try:
             res = urlopen(Request(url, headers={'User-Agent': 'Mozilla/5.0 (bitbake/lib/layerindex)'}, unverifiable=True))
         except urllib.error.HTTPError as e:
-            logger.debug(1, "HTTP Error: %s: %s" % (e.code, e.reason))
-            logger.debug(1, " Requested: %s" % (url))
-            logger.debug(1, " Actual:    %s" % (e.geturl()))
+            logger.debug("HTTP Error: %s: %s" % (e.code, e.reason))
+            logger.debug(" Requested: %s" % (url))
+            logger.debug(" Actual:    %s" % (e.geturl()))
 
             if e.code == 404:
-                logger.debug(1, "Request not found.")
+                logger.debug("Request not found.")
                 raise LayerIndexFetchError(url, e)
             else:
-                logger.debug(1, "Headers:\n%s" % (e.headers))
+                logger.debug("Headers:\n%s" % (e.headers))
                 raise LayerIndexFetchError(url, e)
         except OSError as e:
             error = 0
@@ -169,7 +170,7 @@ class LayerIndex():
                 raise LayerIndexFetchError(url, "Unable to fetch OSError exception: %s" % e)
 
         finally:
-            logger.debug(1, "...fetching %s (%s), done." % (url, ["without authentication", "with authentication"][bool(username)]))
+            logger.debug("...fetching %s (%s), done." % (url, ["without authentication", "with authentication"][bool(username)]))
 
         return res
 
@@ -204,14 +205,14 @@ The format of the indexURI:
         if reload:
             self.indexes = []
 
-        logger.debug(1, 'Loading: %s' % indexURI)
+        logger.debug('Loading: %s' % indexURI)
 
         if not self.plugins:
             raise LayerIndexException("No LayerIndex Plugins available")
 
         for plugin in self.plugins:
             # Check if the plugin was initialized
-            logger.debug(1, 'Trying %s' % plugin.__class__)
+            logger.debug('Trying %s' % plugin.__class__)
             if not hasattr(plugin, 'type') or not plugin.type:
                 continue
             try:
@@ -219,11 +220,11 @@ The format of the indexURI:
                 indexEnt = plugin.load_index(indexURI, load)
                 break
             except LayerIndexPluginUrlError as e:
-                logger.debug(1, "%s doesn't support %s" % (plugin.type, e.url))
+                logger.debug("%s doesn't support %s" % (plugin.type, e.url))
             except NotImplementedError:
                 pass
         else:
-            logger.debug(1, "No plugins support %s" % indexURI)
+            logger.debug("No plugins support %s" % indexURI)
             raise LayerIndexException("No plugins support %s" % indexURI)
 
         # Mark CONFIG data as something we've added...
@@ -254,20 +255,20 @@ will write out the individual elements split by layer and related components.
 
         for plugin in self.plugins:
             # Check if the plugin was initialized
-            logger.debug(1, 'Trying %s' % plugin.__class__)
+            logger.debug('Trying %s' % plugin.__class__)
             if not hasattr(plugin, 'type') or not plugin.type:
                 continue
             try:
                 plugin.store_index(indexURI, index)
                 break
             except LayerIndexPluginUrlError as e:
-                logger.debug(1, "%s doesn't support %s" % (plugin.type, e.url))
+                logger.debug("%s doesn't support %s" % (plugin.type, e.url))
             except NotImplementedError:
-                logger.debug(1, "Store not implemented in %s" % plugin.type)
+                logger.debug("Store not implemented in %s" % plugin.type)
                 pass
         else:
-            logger.debug(1, "No plugins support %s" % url)
-            raise LayerIndexException("No plugins support %s" % url)
+            logger.debug("No plugins support %s" % indexURI)
+            raise LayerIndexException("No plugins support %s" % indexURI)
 
 
     def is_empty(self):
@@ -291,7 +292,7 @@ layerBranches set.  If not, they are effectively blank.'''
            the default configuration until the first vcs_url/branch match.'''
 
         for index in self.indexes:
-            logger.debug(1, ' searching %s' % index.config['DESCRIPTION'])
+            logger.debug(' searching %s' % index.config['DESCRIPTION'])
             layerBranch = index.find_vcs_url(vcs_url, [branch])
             if layerBranch:
                 return layerBranch
@@ -303,7 +304,7 @@ layerBranches set.  If not, they are effectively blank.'''
            If a branch has not been specified, we will iterate over the branches in
            the default configuration until the first collection/branch match.'''
 
-        logger.debug(1, 'find_collection: %s (%s) %s' % (collection, version, branch))
+        logger.debug('find_collection: %s (%s) %s' % (collection, version, branch))
 
         if branch:
             branches = [branch]
@@ -311,12 +312,12 @@ layerBranches set.  If not, they are effectively blank.'''
             branches = None
 
         for index in self.indexes:
-            logger.debug(1, ' searching %s' % index.config['DESCRIPTION'])
+            logger.debug(' searching %s' % index.config['DESCRIPTION'])
             layerBranch = index.find_collection(collection, version, branches)
             if layerBranch:
                 return layerBranch
         else:
-            logger.debug(1, 'Collection %s (%s) not found for branch (%s)' % (collection, version, branch))
+            logger.debug('Collection %s (%s) not found for branch (%s)' % (collection, version, branch))
         return None
 
     def find_layerbranch(self, name, branch=None):
@@ -407,7 +408,7 @@ layerBranches set.  If not, they are effectively blank.'''
                                               version=deplayerbranch.version
                                           )
                         if rdeplayerbranch != deplayerbranch:
-                                logger.debug(1, 'Replaced %s:%s:%s with %s:%s:%s' % \
+                                logger.debug('Replaced %s:%s:%s with %s:%s:%s' % \
                                       (deplayerbranch.index.config['DESCRIPTION'],
                                        deplayerbranch.branch.name,
                                        deplayerbranch.layer.name,
@@ -657,7 +658,7 @@ class LayerIndexObj():
             if obj.id in self._index[indexname]:
                 if self._index[indexname][obj.id] == obj:
                     continue
-                raise LayerIndexError('Conflict adding object %s(%s) to index' % (indexname, obj.id))
+                raise LayerIndexException('Conflict adding object %s(%s) to index' % (indexname, obj.id))
             self._index[indexname][obj.id] = obj
 
     def add_raw_element(self, indexname, objtype, rawobjs):
@@ -842,11 +843,11 @@ class LayerIndexObj():
 
         def _resolve_dependencies(layerbranches, ignores, dependencies, invalid):
             for layerbranch in layerbranches:
-                if ignores and layerBranch.layer.name in ignores:
+                if ignores and layerbranch.layer.name in ignores:
                     continue
 
-                for layerdependency in layerbranch.index.layerDependencies_layerBranchId[layerBranch.id]:
-                    deplayerbranch = layerDependency.dependency_layerBranch
+                for layerdependency in layerbranch.index.layerDependencies_layerBranchId[layerbranch.id]:
+                    deplayerbranch = layerdependency.dependency_layerBranch
 
                     if ignores and deplayerbranch.layer.name in ignores:
                         continue
@@ -1120,7 +1121,7 @@ class LayerBranch(LayerIndexItemObj):
     @property
     def branch(self):
         try:
-            logger.debug(1, "Get branch object from branches[%s]" % (self.branch_id))
+            logger.debug("Get branch object from branches[%s]" % (self.branch_id))
             return self.index.branches[self.branch_id]
         except KeyError:
             raise AttributeError('Unable to find branches in index to map branch_id %s' % self.branch_id)
@@ -1148,7 +1149,7 @@ class LayerBranch(LayerIndexItemObj):
 
     @actual_branch.setter
     def actual_branch(self, value):
-        logger.debug(1, "Set actual_branch to %s .. name is %s" % (value, self.branch.name))
+        logger.debug("Set actual_branch to %s .. name is %s" % (value, self.branch.name))
         if value != self.branch.name:
             self._setattr('actual_branch', value, prop=False)
         else:
diff --git a/bitbake/lib/layerindexlib/cooker.py b/bitbake/lib/layerindexlib/cooker.py
index 65b23d08..2de6e5fa 100644
--- a/bitbake/lib/layerindexlib/cooker.py
+++ b/bitbake/lib/layerindexlib/cooker.py
@@ -4,6 +4,7 @@
 #
 
 import logging
+import os
 
 from collections import defaultdict
 
@@ -73,7 +74,7 @@ class CookerPlugin(layerindexlib.plugin.IndexPlugin):
         d = self.layerindex.data
 
         if not branches:
-            raise LayerIndexFetchError("No branches specified for _load_bblayers!")
+            raise layerindexlib.LayerIndexFetchError("No branches specified for _load_bblayers!")
 
         index = layerindexlib.LayerIndexObj()
 
@@ -172,7 +173,7 @@ class CookerPlugin(layerindexlib.plugin.IndexPlugin):
         else:
             branches = ['HEAD']
 
-        logger.debug(1, "Loading cooker data branches %s" % branches)
+        logger.debug("Loading cooker data branches %s" % branches)
 
         index = self._load_bblayers(branches=branches)
 
@@ -202,7 +203,7 @@ class CookerPlugin(layerindexlib.plugin.IndexPlugin):
                     try:
                         depDict = bb.utils.explode_dep_versions2(deps)
                     except bb.utils.VersionStringException as vse:
-                        bb.fatal('Error parsing LAYERDEPENDS_%s: %s' % (c, str(vse)))
+                        bb.fatal('Error parsing LAYERDEPENDS_%s: %s' % (collection, str(vse)))
 
                     for dep, oplist in list(depDict.items()):
                         # We need to search ourselves, so use the _ version...
@@ -219,7 +220,7 @@ class CookerPlugin(layerindexlib.plugin.IndexPlugin):
                                         required=required, layerbranch=layerBranchId,
                                         dependency=depLayerBranch.layer_id)
 
-                        logger.debug(1, '%s requires %s' % (layerDependency.layer.name, layerDependency.dependency.name))
+                        logger.debug('%s requires %s' % (layerDependency.layer.name, layerDependency.dependency.name))
                         index.add_element("layerDependencies", [layerDependency])
 
                     return layerDependencyId
@@ -268,7 +269,7 @@ class CookerPlugin(layerindexlib.plugin.IndexPlugin):
 
                     layer = bb.utils.get_file_layer(realfn[0], self.config_data)
 
-                    depBranchId = collection_layerbranch[layer]
+                    depBranchId = collection[layer]
 
                     recipeId += 1
                     recipe = layerindexlib.Recipe(index, None)
diff --git a/bitbake/lib/layerindexlib/restapi.py b/bitbake/lib/layerindexlib/restapi.py
index 21fd1441..26a1c967 100644
--- a/bitbake/lib/layerindexlib/restapi.py
+++ b/bitbake/lib/layerindexlib/restapi.py
@@ -5,9 +5,13 @@
 
 import logging
 import json
+import os
+
 from urllib.parse import unquote
 from urllib.parse import urlparse
 
+import bb
+
 import layerindexlib
 import layerindexlib.plugin
 
@@ -78,7 +82,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
 
 
         def load_cache(path, index, branches=[]):
-            logger.debug(1, 'Loading json file %s' % path)
+            logger.debug('Loading json file %s' % path)
             with open(path, 'rt', encoding='utf-8') as f:
                 pindex = json.load(f)
 
@@ -98,7 +102,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
             if newpBranch:
                 index.add_raw_element('branches', layerindexlib.Branch, newpBranch)
             else:
-                logger.debug(1, 'No matching branches (%s) in index file(s)' % branches)
+                logger.debug('No matching branches (%s) in index file(s)' % branches)
                 # No matching branches.. return nothing...
                 return
 
@@ -116,7 +120,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
             load_cache(up.path, index, branches)
             return index
 
-        logger.debug(1, 'Loading from dir %s...' % (up.path))
+        logger.debug('Loading from dir %s...' % (up.path))
         for (dirpath, _, filenames) in os.walk(up.path):
             for filename in filenames:
                 if not filename.endswith('.json'):
@@ -140,7 +144,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
         def _get_json_response(apiurl=None, username=None, password=None, retry=True):
             assert apiurl is not None
 
-            logger.debug(1, "fetching %s" % apiurl)
+            logger.debug("fetching %s" % apiurl)
 
             up = urlparse(apiurl)
 
@@ -159,11 +163,11 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
                 parsed = json.loads(res.read().decode('utf-8'))
             except ConnectionResetError:
                 if retry:
-                    logger.debug(1, "%s: Connection reset by peer.  Retrying..." % url)
+                    logger.debug("%s: Connection reset by peer.  Retrying..." % url)
                     parsed = _get_json_response(apiurl=up_stripped.geturl(), username=username, password=password, retry=False)
-                    logger.debug(1, "%s: retry successful.")
+                    logger.debug("%s: retry successful.")
                 else:
-                    raise LayerIndexFetchError('%s: Connection reset by peer.  Is there a firewall blocking your connection?' % apiurl)
+                    raise layerindexlib.LayerIndexFetchError('%s: Connection reset by peer.  Is there a firewall blocking your connection?' % apiurl)
 
             return parsed
 
@@ -203,25 +207,25 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
         if "*" not in branches:
             filter = "?filter=name:%s" % "OR".join(branches)
 
-        logger.debug(1, "Loading %s from %s" % (branches, index.apilinks['branches']))
+        logger.debug("Loading %s from %s" % (branches, index.apilinks['branches']))
 
         # The link won't include username/password, so pull it from the original url
         pindex['branches'] = _get_json_response(index.apilinks['branches'] + filter,
                                                     username=up.username, password=up.password)
         if not pindex['branches']:
-            logger.debug(1, "No valid branches (%s) found at url %s." % (branch, url))
+            logger.debug("No valid branches (%s) found at url %s." % (branch, url))
             return index
         index.add_raw_element("branches", layerindexlib.Branch, pindex['branches'])
 
         # Load all of the layerItems (these can not be easily filtered)
-        logger.debug(1, "Loading %s from %s" % ('layerItems', index.apilinks['layerItems']))
+        logger.debug("Loading %s from %s" % ('layerItems', index.apilinks['layerItems']))
 
 
         # The link won't include username/password, so pull it from the original url
         pindex['layerItems'] = _get_json_response(index.apilinks['layerItems'],
                                                   username=up.username, password=up.password)
         if not pindex['layerItems']:
-            logger.debug(1, "No layers were found at url %s." % (url))
+            logger.debug("No layers were found at url %s." % (url))
             return index
         index.add_raw_element("layerItems", layerindexlib.LayerItem, pindex['layerItems'])
 
@@ -231,13 +235,13 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
         for branch in index.branches:
             filter = "?filter=branch__name:%s" % index.branches[branch].name
 
-            logger.debug(1, "Loading %s from %s" % ('layerBranches', index.apilinks['layerBranches']))
+            logger.debug("Loading %s from %s" % ('layerBranches', index.apilinks['layerBranches']))
 
             # The link won't include username/password, so pull it from the original url
             pindex['layerBranches'] = _get_json_response(index.apilinks['layerBranches'] + filter,
                                                   username=up.username, password=up.password)
             if not pindex['layerBranches']:
-                logger.debug(1, "No valid layer branches (%s) found at url %s." % (branches or "*", url))
+                logger.debug("No valid layer branches (%s) found at url %s." % (branches or "*", url))
                 return index
             index.add_raw_element("layerBranches", layerindexlib.LayerBranch, pindex['layerBranches'])
 
@@ -252,7 +256,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
                                    ("distros", layerindexlib.Distro)]:
                 if lName not in load:
                     continue
-                logger.debug(1, "Loading %s from %s" % (lName, index.apilinks[lName]))
+                logger.debug("Loading %s from %s" % (lName, index.apilinks[lName]))
 
                 # The link won't include username/password, so pull it from the original url
                 pindex[lName] = _get_json_response(index.apilinks[lName] + filter,
@@ -279,7 +283,7 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
         if up.scheme != 'file':
             raise layerindexlib.plugin.LayerIndexPluginUrlError(self.type, url)
 
-        logger.debug(1, "Storing to %s..." % up.path)
+        logger.debug("Storing to %s..." % up.path)
 
         try:
             layerbranches = index.layerBranches
@@ -295,12 +299,12 @@ class RestApiPlugin(layerindexlib.plugin.IndexPlugin):
                     if getattr(index, objects)[obj].layerbranch_id == layerbranchid:
                        filtered.append(getattr(index, objects)[obj]._data)
                 except AttributeError:
-                    logger.debug(1, 'No obj.layerbranch_id: %s' % objects)
+                    logger.debug('No obj.layerbranch_id: %s' % objects)
                     # No simple filter method, just include it...
                     try:
                         filtered.append(getattr(index, objects)[obj]._data)
                     except AttributeError:
-                        logger.debug(1, 'No obj._data: %s %s' % (objects, type(obj)))
+                        logger.debug('No obj._data: %s %s' % (objects, type(obj)))
                         filtered.append(obj)
             return filtered
 
diff --git a/bitbake/lib/layerindexlib/tests/cooker.py b/bitbake/lib/layerindexlib/tests/cooker.py
index 1d0685e0..5ddf89aa 100644
--- a/bitbake/lib/layerindexlib/tests/cooker.py
+++ b/bitbake/lib/layerindexlib/tests/cooker.py
@@ -72,7 +72,7 @@ class LayerIndexCookerTest(LayersTest):
 
     def test_find_collection(self):
         def _check(collection, expected):
-            self.logger.debug(1, "Looking for collection %s..." % collection)
+            self.logger.debug("Looking for collection %s..." % collection)
             result = self.layerindex.find_collection(collection)
             if expected:
                 self.assertIsNotNone(result, msg="Did not find %s when it shouldn't be there" % collection)
@@ -91,7 +91,7 @@ class LayerIndexCookerTest(LayersTest):
 
     def test_find_layerbranch(self):
         def _check(name, expected):
-            self.logger.debug(1, "Looking for layerbranch %s..." % name)
+            self.logger.debug("Looking for layerbranch %s..." % name)
             result = self.layerindex.find_layerbranch(name)
             if expected:
                 self.assertIsNotNone(result, msg="Did not find %s when it shouldn't be there" % collection)
diff --git a/bitbake/lib/layerindexlib/tests/restapi.py b/bitbake/lib/layerindexlib/tests/restapi.py
index e5ccafe5..33b5c1c4 100644
--- a/bitbake/lib/layerindexlib/tests/restapi.py
+++ b/bitbake/lib/layerindexlib/tests/restapi.py
@@ -57,11 +57,11 @@ class LayerIndexWebRestApiTest(LayersTest):
                type in self.layerindex.indexes[0].config['local']:
                 continue
             for id in getattr(self.layerindex.indexes[0], type):
-                self.logger.debug(1, "type %s" % (type))
+                self.logger.debug("type %s" % (type))
 
                 self.assertTrue(id in getattr(reload.indexes[0], type), msg="Id number not in reloaded index")
 
-                self.logger.debug(1, "%s ? %s" % (getattr(self.layerindex.indexes[0], type)[id], getattr(reload.indexes[0], type)[id]))
+                self.logger.debug("%s ? %s" % (getattr(self.layerindex.indexes[0], type)[id], getattr(reload.indexes[0], type)[id]))
 
                 self.assertEqual(getattr(self.layerindex.indexes[0], type)[id], getattr(reload.indexes[0], type)[id], msg="Reloaded contents different")
 
@@ -80,11 +80,11 @@ class LayerIndexWebRestApiTest(LayersTest):
                type in self.layerindex.indexes[0].config['local']:
                 continue
             for id in getattr(self.layerindex.indexes[0] ,type):
-                self.logger.debug(1, "type %s" % (type))
+                self.logger.debug("type %s" % (type))
 
                 self.assertTrue(id in getattr(reload.indexes[0], type), msg="Id number missing from reloaded data")
 
-                self.logger.debug(1, "%s ? %s" % (getattr(self.layerindex.indexes[0] ,type)[id], getattr(reload.indexes[0], type)[id]))
+                self.logger.debug("%s ? %s" % (getattr(self.layerindex.indexes[0] ,type)[id], getattr(reload.indexes[0], type)[id]))
 
                 self.assertEqual(getattr(self.layerindex.indexes[0] ,type)[id], getattr(reload.indexes[0], type)[id], msg="reloaded data does not match original")
 
@@ -111,14 +111,14 @@ class LayerIndexWebRestApiTest(LayersTest):
                 if dep.layer.name == 'meta-python':
                     break
             else:
-                self.logger.debug(1, "meta-python was not found")
-                self.assetTrue(False)
+                self.logger.debug("meta-python was not found")
+                raise self.failureException
 
             # Only check the first element...
             break
         else:
             # Empty list, this is bad.
-            self.logger.debug(1, "Empty list of dependencies")
+            self.logger.debug("Empty list of dependencies")
             self.assertIsNotNone(first, msg="Empty list of dependencies")
 
             # Last dep should be the requested item
@@ -128,7 +128,7 @@ class LayerIndexWebRestApiTest(LayersTest):
     @skipIfNoNetwork()
     def test_find_collection(self):
         def _check(collection, expected):
-            self.logger.debug(1, "Looking for collection %s..." % collection)
+            self.logger.debug("Looking for collection %s..." % collection)
             result = self.layerindex.find_collection(collection)
             if expected:
                 self.assertIsNotNone(result, msg="Did not find %s when it should be there" % collection)
@@ -148,11 +148,11 @@ class LayerIndexWebRestApiTest(LayersTest):
     @skipIfNoNetwork()
     def test_find_layerbranch(self):
         def _check(name, expected):
-            self.logger.debug(1, "Looking for layerbranch %s..." % name)
+            self.logger.debug("Looking for layerbranch %s..." % name)
 
             for index in self.layerindex.indexes:
                 for layerbranchid in index.layerBranches:
-                    self.logger.debug(1, "Present: %s" % index.layerBranches[layerbranchid].layer.name)
+                    self.logger.debug("Present: %s" % index.layerBranches[layerbranchid].layer.name)
             result = self.layerindex.find_layerbranch(name)
             if expected:
                 self.assertIsNotNone(result, msg="Did not find %s when it should be there" % collection)
diff --git a/bitbake/lib/ply/lex.py b/bitbake/lib/ply/lex.py
index 267ec100..182f2e83 100644
--- a/bitbake/lib/ply/lex.py
+++ b/bitbake/lib/ply/lex.py
@@ -705,11 +705,7 @@ class LexerReflect(object):
 
         # Sort the functions by line number
         for f in self.funcsym.values():
-            if sys.version_info[0] < 3:
-                f.sort(lambda x,y: cmp(func_code(x[1]).co_firstlineno,func_code(y[1]).co_firstlineno))
-            else:
-                # Python 3.0
-                f.sort(key=lambda x: func_code(x[1]).co_firstlineno)
+            f.sort(key=lambda x: func_code(x[1]).co_firstlineno)
 
         # Sort the strings by regular expression length
         for s in self.strsym.values():
diff --git a/bitbake/lib/ply/yacc.py b/bitbake/lib/ply/yacc.py
index 561784f2..46e7dc96 100644
--- a/bitbake/lib/ply/yacc.py
+++ b/bitbake/lib/ply/yacc.py
@@ -1205,7 +1205,7 @@ class Production(object):
 
         # Precompute the list of productions immediately following.  Hack. Remove later
         try:
-            p.lr_after = Prodnames[p.prod[n+1]]
+            p.lr_after = self.Prodnames[p.prod[n+1]]
         except (IndexError,KeyError):
             p.lr_after = []
         try:
diff --git a/bitbake/lib/toaster/orm/fixtures/oe-core.xml b/bitbake/lib/toaster/orm/fixtures/oe-core.xml
index fd93f4d8..026d9486 100644
--- a/bitbake/lib/toaster/orm/fixtures/oe-core.xml
+++ b/bitbake/lib/toaster/orm/fixtures/oe-core.xml
@@ -23,9 +23,9 @@
     <field type="CharField" name="branch">master</field>
   </object>
   <object model="orm.bitbakeversion" pk="4">
-    <field type="CharField" name="name">zeus</field>
+    <field type="CharField" name="name">gatesgarth</field>
     <field type="CharField" name="giturl">git://git.openembedded.org/bitbake</field>
-    <field type="CharField" name="branch">1.44</field>
+    <field type="CharField" name="branch">1.48</field>
   </object>
 
   <!-- Releases available -->
@@ -51,11 +51,11 @@
     <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/\"&gt;OpenEmbedded master&lt;/a&gt; branch.</field>
   </object>
   <object model="orm.release" pk="4">
-    <field type="CharField" name="name">zeus</field>
-    <field type="CharField" name="description">Openembedded Zeus</field>
+    <field type="CharField" name="name">gatesgarth</field>
+    <field type="CharField" name="description">Openembedded Gatesgarth</field>
     <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field>
-    <field type="CharField" name="branch_name">zeus</field>
-    <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/?h=zeus\"&gt;OpenEmbedded Zeus&lt;/a&gt; branch.</field>
+    <field type="CharField" name="branch_name">gatesgarth</field>
+    <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/?h=gatesgarth\"&gt;OpenEmbedded Gatesgarth&lt;/a&gt; branch.</field>
   </object>
 
   <!-- Default layers for each release -->
diff --git a/bitbake/lib/toaster/orm/fixtures/poky.xml b/bitbake/lib/toaster/orm/fixtures/poky.xml
index 902bc88a..a468a54c 100644
--- a/bitbake/lib/toaster/orm/fixtures/poky.xml
+++ b/bitbake/lib/toaster/orm/fixtures/poky.xml
@@ -26,9 +26,9 @@
     <field type="CharField" name="dirpath">bitbake</field>
   </object>
   <object model="orm.bitbakeversion" pk="4">
-    <field type="CharField" name="name">zeus</field>
+    <field type="CharField" name="name">gatesgarth</field>
     <field type="CharField" name="giturl">git://git.yoctoproject.org/poky</field>
-    <field type="CharField" name="branch">zeus</field>
+    <field type="CharField" name="branch">gatesgarth</field>
     <field type="CharField" name="dirpath">bitbake</field>
   </object>
 
@@ -56,11 +56,11 @@
     <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/"&gt;Yocto Project Master branch&lt;/a&gt;.</field>
   </object>
   <object model="orm.release" pk="4">
-    <field type="CharField" name="name">zeus</field>
-    <field type="CharField" name="description">Yocto Project 3.0 "Zeus"</field>
+    <field type="CharField" name="name">gatesgarth</field>
+    <field type="CharField" name="description">Yocto Project 3.2 "Gatesgarth"</field>
     <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field>
-    <field type="CharField" name="branch_name">zeus</field>
-    <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?h=zeus"&gt;Yocto Project Zeus branch&lt;/a&gt;.</field>
+    <field type="CharField" name="branch_name">gatesgarth</field>
+    <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?h=gatesgarth"&gt;Yocto Project Gatesgarth branch&lt;/a&gt;.</field>
   </object>
 
   <!-- Default project layers for each release -->
@@ -152,7 +152,7 @@
     <field rel="ManyToOneRel" to="orm.layer" name="layer">1</field>
     <field type="IntegerField" name="layer_source">0</field>
     <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
-    <field type="CharField" name="branch">zeus</field>
+    <field type="CharField" name="branch">gatesgarth</field>
     <field type="CharField" name="dirpath">meta</field>
   </object>
 
@@ -190,7 +190,7 @@
     <field rel="ManyToOneRel" to="orm.layer" name="layer">2</field>
     <field type="IntegerField" name="layer_source">0</field>
     <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
-    <field type="CharField" name="branch">zeus</field>
+    <field type="CharField" name="branch">gatesgarth</field>
     <field type="CharField" name="dirpath">meta-poky</field>
   </object>
 
@@ -228,7 +228,7 @@
     <field rel="ManyToOneRel" to="orm.layer" name="layer">3</field>
     <field type="IntegerField" name="layer_source">0</field>
     <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
-    <field type="CharField" name="branch">zeus</field>
+    <field type="CharField" name="branch">gatesgarth</field>
     <field type="CharField" name="dirpath">meta-yocto-bsp</field>
   </object>
 </django-objects>
diff --git a/bitbake/lib/toaster/orm/management/commands/lsupdates.py b/bitbake/lib/toaster/orm/management/commands/lsupdates.py
index a4dbcaa7..2fbd7be3 100644
--- a/bitbake/lib/toaster/orm/management/commands/lsupdates.py
+++ b/bitbake/lib/toaster/orm/management/commands/lsupdates.py
@@ -68,7 +68,7 @@ class Command(BaseCommand):
                          (what,
                           pec))
         sys.stdout.flush()
-        if int(pec) is 100:
+        if int(pec) == 100:
             sys.stdout.write("\n")
             sys.stdout.flush()
 
diff --git a/bitbake/lib/toaster/tests/functional/functional_helpers.py b/bitbake/lib/toaster/tests/functional/functional_helpers.py
index 455c408e..5c4ea717 100644
--- a/bitbake/lib/toaster/tests/functional/functional_helpers.py
+++ b/bitbake/lib/toaster/tests/functional/functional_helpers.py
@@ -75,7 +75,7 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase):
         try:
             table_element = self.get_table_element(table_id)
             element = table_element.find_element_by_link_text(link_text)
-        except NoSuchElementException as e:
+        except self.NoSuchElementException:
             print('no element found')
             raise
         return element
@@ -86,7 +86,7 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase):
             element_xpath = "//*[@id='" + table_id + "']"
             try:
                 element = self.driver.find_element_by_xpath(element_xpath)
-            except NoSuchElementException as e:
+            except self.NoSuchElementException:
                 raise
             return element
         row = coordinate[0]
@@ -96,7 +96,7 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase):
             element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]"
             try:
                 element = self.driver.find_element_by_xpath(element_xpath)
-            except NoSuchElementException as e:
+            except self.NoSuchElementException:
                 return False
             return element
 #now we are looking for an element with specified X and Y
@@ -105,6 +105,6 @@ class SeleniumFunctionalTestCase(SeleniumTestCaseBase):
         element_xpath = "//*[@id='" + table_id + "']/tbody/tr[" + str(row) + "]/td[" + str(column) + "]"
         try:
             element = self.driver.find_element_by_xpath(element_xpath)
-        except NoSuchElementException as e:
+        except self.NoSuchElementException:
             return False
         return element
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index 4f720648..9e19cc33 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -123,7 +123,7 @@
               {% endif %}
             {% endif %}
               <li id="navbar-docs">
-              <a target="_blank" href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html">
+              <a target="_blank" href="https://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html">
                 <i class="glyphicon glyphicon-book"></i>
                 Documentation
               </a>
diff --git a/bitbake/lib/toaster/toastergui/templates/configvars.html b/bitbake/lib/toaster/toastergui/templates/configvars.html
index ca2e1eab..33fef931 100644
--- a/bitbake/lib/toaster/toastergui/templates/configvars.html
+++ b/bitbake/lib/toaster/toastergui/templates/configvars.html
@@ -66,7 +66,7 @@
         <td class="description">
             {% if variable.description %}
                 {{variable.description}}
-                <a href="http://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-{{variable.variable_name|variable_parent_name}}" target="_blank">
+                <a href="https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-{{variable.variable_name|variable_parent_name}}" target="_blank">
                 <span class="glyphicon glyphicon-new-window get-info"></span></a>
             {% endif %}
         </td>
diff --git a/bitbake/lib/toaster/toastergui/templates/landing.html b/bitbake/lib/toaster/toastergui/templates/landing.html
index 70c7359f..bfaaf6fc 100644
--- a/bitbake/lib/toaster/toastergui/templates/landing.html
+++ b/bitbake/lib/toaster/toastergui/templates/landing.html
@@ -12,10 +12,10 @@
             <div class="col-md-6">
               <h1>This is Toaster</h1>
 
-              <p>A web interface to <a href="http://www.openembedded.org">OpenEmbedded</a> and <a href="http://www.yoctoproject.org/tools-resources/projects/bitbake">BitBake</a>, the <a href="http://www.yoctoproject.org">Yocto Project</a> build system.</p>
+              <p>A web interface to <a href="https://www.openembedded.org">OpenEmbedded</a> and <a href="https://www.yoctoproject.org/tools-resources/projects/bitbake">BitBake</a>, the <a href="https://www.yoctoproject.org">Yocto Project</a> build system.</p>
 
 		          <p class="top-air">
-		            <a class="btn btn-info btn-lg" href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#toaster-manual-setup-and-use">
+		            <a class="btn btn-info btn-lg" href="https://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#toaster-manual-setup-and-use">
 			            Toaster is ready to capture your command line builds
 		            </a>
 		          </p>
@@ -33,7 +33,7 @@
                   Toaster has no layer information. Without layer information, you cannot run builds. To generate layer information you can:
                   <ul>
                     <li>
-                      <a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a>
+                      <a href="https://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a>
                     </li>
                     <li>
 			                <a href="{% url 'newproject' %}">Create a project</a>, then import layers
@@ -44,7 +44,7 @@
 
               <ul class="list-unstyled lead">
                 <li>
-                  <a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html">
+                  <a href="https://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html">
                     Read the Toaster manual
                   </a>
                 </li>
diff --git a/bitbake/lib/toaster/toastergui/templates/landing_not_managed.html b/bitbake/lib/toaster/toastergui/templates/landing_not_managed.html
index baa4b72c..e7200b84 100644
--- a/bitbake/lib/toaster/toastergui/templates/landing_not_managed.html
+++ b/bitbake/lib/toaster/toastergui/templates/landing_not_managed.html
@@ -20,7 +20,7 @@
      <p">
      The 'Build' mode allows you to configure and run your Yocto Project builds from Toaster.
      <ul>
-       <li><a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#intro-modes">
+       <li><a href="https://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#intro-modes">
        Read about the 'Build' mode
        </a></li>
        <li><a href="/">
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html
index fa41e3c9..d8ad2c79 100644
--- a/bitbake/lib/toaster/toastergui/templates/project.html
+++ b/bitbake/lib/toaster/toastergui/templates/project.html
@@ -139,7 +139,7 @@
         <ul>
           <li><a href="{% url 'projectlayers' project.id %}">Choose from the layers compatible with this project</a></li>
           <li><a href="{% url 'importlayer' project.id %}">Import a layer</a></li>
-          <li><a href="http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the documentation</a></li>
+          <li><a href="https://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the documentation</a></li>
           <li>Or type a layer name below</li>
         </ul>
       </div>
diff --git a/bitbake/lib/toaster/toastergui/templates/project_specific.html b/bitbake/lib/toaster/toastergui/templates/project_specific.html
index f625d18b..42725c0d 100644
--- a/bitbake/lib/toaster/toastergui/templates/project_specific.html
+++ b/bitbake/lib/toaster/toastergui/templates/project_specific.html
@@ -137,7 +137,7 @@
         <ul>
           <li><a href="{% url 'projectlayers' project.id %}">Choose from the layers compatible with this project</a></li>
           <li><a href="{% url 'importlayer' project.id %}">Import a layer</a></li>
-          <li><a href="http://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the documentation</a></li>
+          <li><a href="https://www.yoctoproject.org/docs/current/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the documentation</a></li>
           <li>Or type a layer name below</li>
         </ul>
       </div>
diff --git a/bitbake/lib/toaster/toastergui/templates/projectconf.html b/bitbake/lib/toaster/toastergui/templates/projectconf.html
index fb20b26f..bd49f1f5 100644
--- a/bitbake/lib/toaster/toastergui/templates/projectconf.html
+++ b/bitbake/lib/toaster/toastergui/templates/projectconf.html
@@ -201,12 +201,12 @@
           <p>Toaster cannot set any variables that impact 1) the configuration of the build servers,
           or 2) where artifacts produced by the build are stored. Such variables include: </p>
           <p>
-          <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-BB_DISKMON_DIRS" target="_blank">BB_DISKMON_DIRS</a></code>
-          <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-BB_NUMBER_THREADS" target="_blank">BB_NUMBER_THREADS</a></code>
+          <code><a href="https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-BB_DISKMON_DIRS" target="_blank">BB_DISKMON_DIRS</a></code>
+          <code><a href="https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-BB_NUMBER_THREADS" target="_blank">BB_NUMBER_THREADS</a></code>
           <code>CVS_PROXY_HOST</code>
           <code>CVS_PROXY_PORT</code>
-          <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-PARALLEL_MAKE" target="_blank">PARALLEL_MAKE</a></code>
-          <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-TMPDIR" target="_blank">TMPDIR</a></code></p>
+          <code><a href="https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-PARALLEL_MAKE" target="_blank">PARALLEL_MAKE</a></code>
+          <code><a href="https://www.yoctoproject.org/docs/current/ref-manual/ref-manual.html#var-TMPDIR" target="_blank">TMPDIR</a></code></p>
           <p>Plus the following standard shell environment variables:</p>
           <p><code>http_proxy</code> <code>ftp_proxy</code> <code>https_proxy</code> <code>all_proxy</code></p>
         </div>
diff --git a/bitbake/lib/toaster/toastermain/management/commands/perf.py b/bitbake/lib/toaster/toastermain/management/commands/perf.py
index 7d629fb3..5c41c5b2 100644
--- a/bitbake/lib/toaster/toastermain/management/commands/perf.py
+++ b/bitbake/lib/toaster/toastermain/management/commands/perf.py
@@ -17,46 +17,46 @@ class Command(BaseCommand):
     help    = "Test the response time for all toaster urls"
 
     def handle(self, *args, **options):
-	root_urlconf = __import__(settings.ROOT_URLCONF)
-	patterns = root_urlconf.urls.urlpatterns
-	global full_url
-	for pat in patterns:
-	    if pat.__class__.__name__ == 'RegexURLResolver':
-		url_root_res = str(pat).split('^')[1].replace('>', '')
-		if 'gui' in url_root_res:
-		    for url_patt in pat.url_patterns:
-			full_url = self.get_full_url(url_patt, url_root_res)
-			info = self.url_info(full_url)
-			status_code = info[0]
-			load_time = info[1]
-			print('Trying \'' + full_url + '\', ' + str(status_code) + ', ' + str(load_time))
+        root_urlconf = __import__(settings.ROOT_URLCONF)
+        patterns = root_urlconf.urls.urlpatterns
+        global full_url
+        for pat in patterns:
+            if pat.__class__.__name__ == 'RegexURLResolver':
+                url_root_res = str(pat).split('^')[1].replace('>', '')
+            if 'gui' in url_root_res:
+                for url_patt in pat.url_patterns:
+                    full_url = self.get_full_url(url_patt, url_root_res)
+                    info = self.url_info(full_url)
+                    status_code = info[0]
+                    load_time = info[1]
+                    print('Trying \'' + full_url + '\', ' + str(status_code) + ', ' + str(load_time))
 
     def get_full_url(self, url_patt, url_root_res):
-	full_url = str(url_patt).split('^')[1].replace('$>', '').replace('(?P<file_path>(?:/[', '/bin/busybox').replace('.*', '')
-	full_url = str(url_root_res + full_url)
-	full_url = re.sub('\(\?P<.*?>\\\d\+\)', '1', full_url)
-	full_url = 'http://localhost:8000/' + full_url
-	return full_url
+        full_url = str(url_patt).split('^')[1].replace('$>', '').replace('(?P<file_path>(?:/[', '/bin/busybox').replace('.*', '')
+        full_url = str(url_root_res + full_url)
+        full_url = re.sub('\(\?P<.*?>\\\d\+\)', '1', full_url)
+        full_url = 'http://localhost:8000/' + full_url
+        return full_url
 
     def url_info(self, full_url):
-	client = Client()
-	info = []
-	try:
-	    resp = client.get(full_url, follow = True)
-	except Exception as e_status_code:
+        client = Client()
+        info = []
+        try:
+            resp = client.get(full_url, follow = True)
+        except Exception as e_status_code:
             self.error('Url: %s, error: %s' % (full_url, e_status_code))
             resp = type('object', (), {'status_code':0, 'content': str(e_status_code)})
-	status_code = resp.status_code
-	info.append(status_code)
-	try:
-	    req = requests.get(full_url)
-	except Exception as e_load_time:
+        status_code = resp.status_code
+        info.append(status_code)
+        try:
+            req = requests.get(full_url)
+        except Exception as e_load_time:
             self.error('Url: %s, error: %s' % (full_url, e_load_time))
-	load_time = req.elapsed
-	info.append(load_time)
-	return info
+        load_time = req.elapsed
+        info.append(load_time)
+        return info
 
     def error(self, *args):
-	for arg in args:
-	    print(arg, end=' ', file=sys.stderr)
-	print(file=sys.stderr)
+        for arg in args:
+            print(arg, end=' ', file=sys.stderr)
+        print(file=sys.stderr)
-- 
2.20.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-02-01 11:42 [PATCH 0/1] Update bitbake to version 1.50.4 Uladzimir Bely
  2022-02-01 11:42 ` [PATCH 1/1] bitbake: Update to 1.50.4 release Uladzimir Bely
@ 2022-02-02  6:25 ` Schmidt, Adriaan
  2022-02-02  6:52   ` Jan Kiszka
  2022-03-25  6:31 ` Anton Mikanovich
  2 siblings, 1 reply; 11+ messages in thread
From: Schmidt, Adriaan @ 2022-02-02  6:25 UTC (permalink / raw)
  To: Uladzimir Bely, isar-users

Uladzimir Bely, 1. Februar 2022 12:42:
> To: isar-users@googlegroups.com
> Subject: [PATCH 0/1] Update bitbake to version 1.50.4
> 
> Bitbake in Isar didn't get updates for almost 1.5 years. At the same time
> the version we use have at least one annoying bug, when messages in log
> files got duplicated if "--verbose" option is used and error happens.
> 
> This was fixed in upstream revision 69c622b744d9, few commits before the
> tag 1.50.4.
> 
> Also, there is 1.52 branch exists (latest tag 1.52.1), but it seems to be
> incompatible with Isar.

One of the major changes is a new syntax for overrides:
https://docs.yoctoproject.org/migration-guides/migration-3.4.html#override-syntax-changes

This will of course break many (all?) downstream layers. But as it has to happen sooner or later, I'd rather vote for "sooner"...

Adriaan


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-02-02  6:25 ` [PATCH 0/1] Update bitbake to version 1.50.4 Schmidt, Adriaan
@ 2022-02-02  6:52   ` Jan Kiszka
  2022-03-28  8:44     ` Henning Schild
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kiszka @ 2022-02-02  6:52 UTC (permalink / raw)
  To: Schmidt, Adriaan, Uladzimir Bely, isar-users

On 02.02.22 07:25, Schmidt, Adriaan wrote:
> Uladzimir Bely, 1. Februar 2022 12:42:
>> To: isar-users@googlegroups.com
>> Subject: [PATCH 0/1] Update bitbake to version 1.50.4
>>
>> Bitbake in Isar didn't get updates for almost 1.5 years. At the same time
>> the version we use have at least one annoying bug, when messages in log
>> files got duplicated if "--verbose" option is used and error happens.
>>
>> This was fixed in upstream revision 69c622b744d9, few commits before the
>> tag 1.50.4.
>>
>> Also, there is 1.52 branch exists (latest tag 1.52.1), but it seems to be
>> incompatible with Isar.
> 
> One of the major changes is a new syntax for overrides:
> https://docs.yoctoproject.org/migration-guides/migration-3.4.html#override-syntax-changes
> 
> This will of course break many (all?) downstream layers. But as it has to happen sooner or later, I'd rather vote for "sooner"...
> 

Yeah, and we likely need to start by updating Isar itself, its imported
OE bits as well as own recipes.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-02-01 11:42 [PATCH 0/1] Update bitbake to version 1.50.4 Uladzimir Bely
  2022-02-01 11:42 ` [PATCH 1/1] bitbake: Update to 1.50.4 release Uladzimir Bely
  2022-02-02  6:25 ` [PATCH 0/1] Update bitbake to version 1.50.4 Schmidt, Adriaan
@ 2022-03-25  6:31 ` Anton Mikanovich
  2022-04-19 12:41   ` Bezdeka, Florian
  2 siblings, 1 reply; 11+ messages in thread
From: Anton Mikanovich @ 2022-03-25  6:31 UTC (permalink / raw)
  To: Uladzimir Bely, isar-users

01.02.2022 14:42, Uladzimir Bely wrote:
> Bitbake in Isar didn't get updates for almost 1.5 years. At the same time
> the version we use have at least one annoying bug, when messages in log
> files got duplicated if "--verbose" option is used and error happens.
>
> This was fixed in upstream revision 69c622b744d9, few commits before the
> tag 1.50.4.
>
> Also, there is 1.52 branch exists (latest tag 1.52.1), but it seems to be
> incompatible with Isar.

Update to bitbake 1.50.4 applied to next, thanks.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-02-02  6:52   ` Jan Kiszka
@ 2022-03-28  8:44     ` Henning Schild
  0 siblings, 0 replies; 11+ messages in thread
From: Henning Schild @ 2022-03-28  8:44 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Schmidt, Adriaan, Uladzimir Bely, isar-users

Am Wed, 2 Feb 2022 07:52:26 +0100
schrieb Jan Kiszka <jan.kiszka@siemens.com>:

> On 02.02.22 07:25, Schmidt, Adriaan wrote:
> > Uladzimir Bely, 1. Februar 2022 12:42:  
> >> To: isar-users@googlegroups.com
> >> Subject: [PATCH 0/1] Update bitbake to version 1.50.4
> >>
> >> Bitbake in Isar didn't get updates for almost 1.5 years. At the
> >> same time the version we use have at least one annoying bug, when
> >> messages in log files got duplicated if "--verbose" option is used
> >> and error happens.
> >>
> >> This was fixed in upstream revision 69c622b744d9, few commits
> >> before the tag 1.50.4.
> >>
> >> Also, there is 1.52 branch exists (latest tag 1.52.1), but it
> >> seems to be incompatible with Isar.  
> > 
> > One of the major changes is a new syntax for overrides:
> > https://docs.yoctoproject.org/migration-guides/migration-3.4.html#override-syntax-changes
> > 
> > This will of course break many (all?) downstream layers. But as it
> > has to happen sooner or later, I'd rather vote for "sooner"... 
> 
> Yeah, and we likely need to start by updating Isar itself, its
> imported OE bits as well as own recipes.

In fact that task should have been a second or even more patches in the
same series. Now we have a wild mix for an updated bitbake and many
outdated forked bits.

>From the back of my head that should affect.

patch class, sstate, devshell, wks files (maybe part of wic) and some
more bits.

Not sure if things have been upstreamed in the meantime and can maybe
be dropped from isar.

Henning

> Jan
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-03-25  6:31 ` Anton Mikanovich
@ 2022-04-19 12:41   ` Bezdeka, Florian
  2022-04-19 12:51     ` Henning Schild
  0 siblings, 1 reply; 11+ messages in thread
From: Bezdeka, Florian @ 2022-04-19 12:41 UTC (permalink / raw)
  To: amikan, ubely, isar-users; +Cc: jan.kiszka, Schild, Henning

Hi all,

On Fri, 2022-03-25 at 09:31 +0300, Anton Mikanovich wrote:
> 01.02.2022 14:42, Uladzimir Bely wrote:
> > Bitbake in Isar didn't get updates for almost 1.5 years. At the same time
> > the version we use have at least one annoying bug, when messages in log
> > files got duplicated if "--verbose" option is used and error happens.
> > 
> > This was fixed in upstream revision 69c622b744d9, few commits before the
> > tag 1.50.4.
> > 
> > Also, there is 1.52 branch exists (latest tag 1.52.1), but it seems to be
> > incompatible with Isar.
> 
> Update to bitbake 1.50.4 applied to next, thanks.
> 

this seems to trigger a build failure when trying to use debian
bookworm as distro, there is no debian-bookworm-backports.list file.

ERROR: ExpansionError during parsing /work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap-target.bb################################################ | ETA: 0:00:00
Traceback (most recent call last):
File "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc", line 181, in get_distro_needs_https_support(d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>):
def get_distro_needs_https_support(d):
> if get_distro_have_https_source(d):
return "https-support"
File "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc", line 172, in get_distro_have_https_source(d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>):
def get_distro_have_https_source(d):
> return any(source[2].startswith("https://") for source in generate_distro_sources(d))

File "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc", line 172, in <genexpr>(.0=<generator object generate_distro_sources at 0x7fc5bed36318>):
def get_distro_have_https_source(d):
> return any(source[2].startswith("https://") for source in generate_distro_sources(d))

File "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc", line 157, in generate_distro_sources(d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>):
for entry in apt_sources_list:
> entry_real = bb.parse.resolve_file(entry, d)
with open(entry_real, "r") as in_fd:
File "/work/isar/bitbake/lib/bb/parse/__init__.py", line 125, in resolve_file(fn='conf/distro/debian-bookworm-backports.list', d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>):
if not newfn:
> raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath))
fn = newfn
bb.data_smart.ExpansionError: Failure expanding variable OVERRIDES, expression was amd64::qemuamd64:debian-bookworm:forcevariable:${@get_distro_needs_https_support(d)} which triggered exception FileNotFoundError: [Errno 2] file conf/distro/debian-bookworm-backports.list 


My understanding for now is, that bb.parse.resolve_file() might throw
an IOError when the file can not be found. That might be new, but I
failed to get something from the bb changelog.

Seems we have to revisit all usages of bb.parse.resolve_file(). All of
them are actually in the same file...

Any thoughts?

Regards,
Florian

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-04-19 12:41   ` Bezdeka, Florian
@ 2022-04-19 12:51     ` Henning Schild
  2022-04-19 14:02       ` Bezdeka, Florian
  0 siblings, 1 reply; 11+ messages in thread
From: Henning Schild @ 2022-04-19 12:51 UTC (permalink / raw)
  To: Bezdeka, Florian (T CED SES-DE)
  Cc: amikan, ubely, isar-users, Kiszka, Jan (T CED)

Am Tue, 19 Apr 2022 14:41:14 +0200
schrieb "Bezdeka, Florian (T CED SES-DE)" <florian.bezdeka@siemens.com>:

> Hi all,
> 
> On Fri, 2022-03-25 at 09:31 +0300, Anton Mikanovich wrote:
> > 01.02.2022 14:42, Uladzimir Bely wrote:  
> > > Bitbake in Isar didn't get updates for almost 1.5 years. At the
> > > same time the version we use have at least one annoying bug, when
> > > messages in log files got duplicated if "--verbose" option is
> > > used and error happens.
> > > 
> > > This was fixed in upstream revision 69c622b744d9, few commits
> > > before the tag 1.50.4.
> > > 
> > > Also, there is 1.52 branch exists (latest tag 1.52.1), but it
> > > seems to be incompatible with Isar.  
> > 
> > Update to bitbake 1.50.4 applied to next, thanks.
> >   
> 
> this seems to trigger a build failure when trying to use debian
> bookworm as distro, there is no debian-bookworm-backports.list file.

I think you might be dealing with an issue in your layers. A layer you
might be basing on recently introduced backports for bullseye and does
not yet test for bookworm. Isar itself does not do anything about
backports and does not carry such list files.

regards,
Henning

> ERROR: ExpansionError during parsing
> /work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap-target.bb################################################
> | ETA: 0:00:00 Traceback (most recent call last): File
> "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> line 181, in
> get_distro_needs_https_support(d=<bb.data_smart.DataSmart object at
> 0x7fc5bf873908>): def get_distro_needs_https_support(d):
> > if get_distro_have_https_source(d):  
> return "https-support"
> File
> "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> line 172, in get_distro_have_https_source(d=<bb.data_smart.DataSmart
> object at 0x7fc5bf873908>): def get_distro_have_https_source(d):
> > return any(source[2].startswith("https://") for source in
> > generate_distro_sources(d))  
> 
> File
> "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> line 172, in <genexpr>(.0=<generator object generate_distro_sources
> at 0x7fc5bed36318>): def get_distro_have_https_source(d):
> > return any(source[2].startswith("https://") for source in
> > generate_distro_sources(d))  
> 
> File
> "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> line 157, in generate_distro_sources(d=<bb.data_smart.DataSmart
> object at 0x7fc5bf873908>): for entry in apt_sources_list:
> > entry_real = bb.parse.resolve_file(entry, d)  
> with open(entry_real, "r") as in_fd:
> File "/work/isar/bitbake/lib/bb/parse/__init__.py", line 125, in
> resolve_file(fn='conf/distro/debian-bookworm-backports.list',
> d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>): if not newfn:
> > raise IOError(errno.ENOENT, "file %s not found in %s" % (fn,
> > bbpath))  
> fn = newfn
> bb.data_smart.ExpansionError: Failure expanding variable OVERRIDES,
> expression was
> amd64::qemuamd64:debian-bookworm:forcevariable:${@get_distro_needs_https_support(d)}
> which triggered exception FileNotFoundError: [Errno 2] file
> conf/distro/debian-bookworm-backports.list 
> 
> 
> My understanding for now is, that bb.parse.resolve_file() might throw
> an IOError when the file can not be found. That might be new, but I
> failed to get something from the bb changelog.
> 
> Seems we have to revisit all usages of bb.parse.resolve_file(). All of
> them are actually in the same file...
> 
> Any thoughts?
> 
> Regards,
> Florian


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-04-19 12:51     ` Henning Schild
@ 2022-04-19 14:02       ` Bezdeka, Florian
  2022-04-19 14:26         ` Baurzhan Ismagulov
  2022-04-19 14:35         ` Henning Schild
  0 siblings, 2 replies; 11+ messages in thread
From: Bezdeka, Florian @ 2022-04-19 14:02 UTC (permalink / raw)
  To: Schild, Henning; +Cc: amikan, ubely, isar-users, jan.kiszka

On Tue, 2022-04-19 at 14:51 +0200, Henning Schild wrote:
> Am Tue, 19 Apr 2022 14:41:14 +0200
> schrieb "Bezdeka, Florian (T CED SES-DE)" <florian.bezdeka@siemens.com>:
> 
> > Hi all,
> > 
> > On Fri, 2022-03-25 at 09:31 +0300, Anton Mikanovich wrote:
> > > 01.02.2022 14:42, Uladzimir Bely wrote:  
> > > > Bitbake in Isar didn't get updates for almost 1.5 years. At the
> > > > same time the version we use have at least one annoying bug, when
> > > > messages in log files got duplicated if "--verbose" option is
> > > > used and error happens.
> > > > 
> > > > This was fixed in upstream revision 69c622b744d9, few commits
> > > > before the tag 1.50.4.
> > > > 
> > > > Also, there is 1.52 branch exists (latest tag 1.52.1), but it
> > > > seems to be incompatible with Isar.  
> > > 
> > > Update to bitbake 1.50.4 applied to next, thanks.
> > >   
> > 
> > this seems to trigger a build failure when trying to use debian
> > bookworm as distro, there is no debian-bookworm-backports.list file.
> 
> I think you might be dealing with an issue in your layers. A layer you
> might be basing on recently introduced backports for bullseye and does
> not yet test for bookworm. Isar itself does not do anything about
> backports and does not carry such list files.

Thanks for the idea. 

I was able to find it. But: Should we really fail this way if one of
the distro apt-sources files can not be found?

> 
> regards,
> Henning
> 
> > ERROR: ExpansionError during parsing
> > /work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap-target.bb################################################
> > > ETA: 0:00:00 Traceback (most recent call last): File
> > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > line 181, in
> > get_distro_needs_https_support(d=<bb.data_smart.DataSmart object at
> > 0x7fc5bf873908>): def get_distro_needs_https_support(d):
> > > if get_distro_have_https_source(d):  
> > return "https-support"
> > File
> > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > line 172, in get_distro_have_https_source(d=<bb.data_smart.DataSmart
> > object at 0x7fc5bf873908>): def get_distro_have_https_source(d):
> > > return any(source[2].startswith("https://") for source in
> > > generate_distro_sources(d))  
> > 
> > File
> > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > line 172, in <genexpr>(.0=<generator object generate_distro_sources
> > at 0x7fc5bed36318>): def get_distro_have_https_source(d):
> > > return any(source[2].startswith("https://") for source in
> > > generate_distro_sources(d))  
> > 
> > File
> > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > line 157, in generate_distro_sources(d=<bb.data_smart.DataSmart
> > object at 0x7fc5bf873908>): for entry in apt_sources_list:
> > > entry_real = bb.parse.resolve_file(entry, d)  
> > with open(entry_real, "r") as in_fd:
> > File "/work/isar/bitbake/lib/bb/parse/__init__.py", line 125, in
> > resolve_file(fn='conf/distro/debian-bookworm-backports.list',
> > d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>): if not newfn:
> > > raise IOError(errno.ENOENT, "file %s not found in %s" % (fn,
> > > bbpath))  
> > fn = newfn
> > bb.data_smart.ExpansionError: Failure expanding variable OVERRIDES,
> > expression was
> > amd64::qemuamd64:debian-bookworm:forcevariable:${@get_distro_needs_https_support(d)}
> > which triggered exception FileNotFoundError: [Errno 2] file
> > conf/distro/debian-bookworm-backports.list 
> > 
> > 
> > My understanding for now is, that bb.parse.resolve_file() might throw
> > an IOError when the file can not be found. That might be new, but I
> > failed to get something from the bb changelog.
> > 
> > Seems we have to revisit all usages of bb.parse.resolve_file(). All of
> > them are actually in the same file...
> > 
> > Any thoughts?
> > 
> > Regards,
> > Florian
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-04-19 14:02       ` Bezdeka, Florian
@ 2022-04-19 14:26         ` Baurzhan Ismagulov
  2022-04-19 14:35         ` Henning Schild
  1 sibling, 0 replies; 11+ messages in thread
From: Baurzhan Ismagulov @ 2022-04-19 14:26 UTC (permalink / raw)
  To: isar-users

On Tue, Apr 19, 2022 at 02:02:01PM +0000, Bezdeka, Florian wrote:
> > > > Update to bitbake 1.50.4 applied to next, thanks.
> > > 
> > > this seems to trigger a build failure when trying to use debian
> > > bookworm as distro, there is no debian-bookworm-backports.list file.
> > 
> > I think you might be dealing with an issue in your layers. A layer you
> > might be basing on recently introduced backports for bullseye and does
> > not yet test for bookworm. Isar itself does not do anything about
> > backports and does not carry such list files.
> 
> Thanks for the idea.�
> 
> I was able to find it. But: Should we really fail this way if one of
> the distro apt-sources files can not be found?

Ideally, any exceptions should be wrapped into user-friendly messages, patches
would be certainly welcome.

With kind regards,
Baurzhan.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/1] Update bitbake to version 1.50.4
  2022-04-19 14:02       ` Bezdeka, Florian
  2022-04-19 14:26         ` Baurzhan Ismagulov
@ 2022-04-19 14:35         ` Henning Schild
  1 sibling, 0 replies; 11+ messages in thread
From: Henning Schild @ 2022-04-19 14:35 UTC (permalink / raw)
  To: Bezdeka, Florian (T CED SES-DE)
  Cc: amikan, ubely, isar-users, Kiszka, Jan (T CED)

Am Tue, 19 Apr 2022 16:02:01 +0200
schrieb "Bezdeka, Florian (T CED SES-DE)" <florian.bezdeka@siemens.com>:

> On Tue, 2022-04-19 at 14:51 +0200, Henning Schild wrote:
> > Am Tue, 19 Apr 2022 14:41:14 +0200
> > schrieb "Bezdeka, Florian (T CED SES-DE)"
> > <florian.bezdeka@siemens.com>: 
> > > Hi all,
> > > 
> > > On Fri, 2022-03-25 at 09:31 +0300, Anton Mikanovich wrote:  
> > > > 01.02.2022 14:42, Uladzimir Bely wrote:    
> > > > > Bitbake in Isar didn't get updates for almost 1.5 years. At
> > > > > the same time the version we use have at least one annoying
> > > > > bug, when messages in log files got duplicated if "--verbose"
> > > > > option is used and error happens.
> > > > > 
> > > > > This was fixed in upstream revision 69c622b744d9, few commits
> > > > > before the tag 1.50.4.
> > > > > 
> > > > > Also, there is 1.52 branch exists (latest tag 1.52.1), but it
> > > > > seems to be incompatible with Isar.    
> > > > 
> > > > Update to bitbake 1.50.4 applied to next, thanks.
> > > >     
> > > 
> > > this seems to trigger a build failure when trying to use debian
> > > bookworm as distro, there is no debian-bookworm-backports.list
> > > file.  
> > 
> > I think you might be dealing with an issue in your layers. A layer
> > you might be basing on recently introduced backports for bullseye
> > and does not yet test for bookworm. Isar itself does not do
> > anything about backports and does not carry such list files.  
> 
> Thanks for the idea. 
> 
> I was able to find it. 

Good to hear that.

> But: Should we really fail this way if one of
> the distro apt-sources files can not be found?

We usually develop and test for the good case, so likely or common
mistakes might not get the verbose error messages or warnings they
might deserve.

Feel free to suggest a patch improving the situation. I agree that it
would be better if something told one that a DISTRO_APT_SOURCES or
DISTRO_APT_PREFERENCES file was not found, before one runs into weird
follow-up problems because we lack checks.

regards,
Henning

> > 
> > regards,
> > Henning
> >   
> > > ERROR: ExpansionError during parsing
> > > /work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap-target.bb################################################
> > >  
> > > > ETA: 0:00:00 Traceback (most recent call last): File  
> > > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > > line 181, in
> > > get_distro_needs_https_support(d=<bb.data_smart.DataSmart object
> > > at  
> > > 0x7fc5bf873908>): def get_distro_needs_https_support(d):
> > > > if get_distro_have_https_source(d):    
> > > return "https-support"
> > > File
> > > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > > line 172, in
> > > get_distro_have_https_source(d=<bb.data_smart.DataSmart object at
> > > 0x7fc5bf873908>): def get_distro_have_https_source(d):  
> > > > return any(source[2].startswith("https://") for source in
> > > > generate_distro_sources(d))    
> > > 
> > > File
> > > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > > line 172, in <genexpr>(.0=<generator object
> > > generate_distro_sources at 0x7fc5bed36318>): def
> > > get_distro_have_https_source(d):  
> > > > return any(source[2].startswith("https://") for source in
> > > > generate_distro_sources(d))    
> > > 
> > > File
> > > "/work/isar/meta/recipes-core/isar-bootstrap/isar-bootstrap.inc",
> > > line 157, in generate_distro_sources(d=<bb.data_smart.DataSmart
> > > object at 0x7fc5bf873908>): for entry in apt_sources_list:  
> > > > entry_real = bb.parse.resolve_file(entry, d)    
> > > with open(entry_real, "r") as in_fd:
> > > File "/work/isar/bitbake/lib/bb/parse/__init__.py", line 125, in
> > > resolve_file(fn='conf/distro/debian-bookworm-backports.list',
> > > d=<bb.data_smart.DataSmart object at 0x7fc5bf873908>): if not
> > > newfn:  
> > > > raise IOError(errno.ENOENT, "file %s not found in %s" % (fn,
> > > > bbpath))    
> > > fn = newfn
> > > bb.data_smart.ExpansionError: Failure expanding variable
> > > OVERRIDES, expression was
> > > amd64::qemuamd64:debian-bookworm:forcevariable:${@get_distro_needs_https_support(d)}
> > > which triggered exception FileNotFoundError: [Errno 2] file
> > > conf/distro/debian-bookworm-backports.list 
> > > 
> > > 
> > > My understanding for now is, that bb.parse.resolve_file() might
> > > throw an IOError when the file can not be found. That might be
> > > new, but I failed to get something from the bb changelog.
> > > 
> > > Seems we have to revisit all usages of bb.parse.resolve_file().
> > > All of them are actually in the same file...
> > > 
> > > Any thoughts?
> > > 
> > > Regards,
> > > Florian  
> >   
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-04-19 14:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-01 11:42 [PATCH 0/1] Update bitbake to version 1.50.4 Uladzimir Bely
2022-02-01 11:42 ` [PATCH 1/1] bitbake: Update to 1.50.4 release Uladzimir Bely
2022-02-02  6:25 ` [PATCH 0/1] Update bitbake to version 1.50.4 Schmidt, Adriaan
2022-02-02  6:52   ` Jan Kiszka
2022-03-28  8:44     ` Henning Schild
2022-03-25  6:31 ` Anton Mikanovich
2022-04-19 12:41   ` Bezdeka, Florian
2022-04-19 12:51     ` Henning Schild
2022-04-19 14:02       ` Bezdeka, Florian
2022-04-19 14:26         ` Baurzhan Ismagulov
2022-04-19 14:35         ` Henning Schild

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox