Compare commits

..

237 Commits

Author SHA1 Message Date
Richard Purdie
6a1f33cc40 build-appliance-image: Update to morty head revision
(From OE-Core rev: 55c835c73cc41b6fc809c941c295d62a612e49e0)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:36 +00:00
Alexandru Moise
8ba5b9eae3 openssl: CVE: CVE-2017-3731
If an SSL/TLS server or client is running on a 32-bit host, and a
specific cipher is being used, then a truncated packet can cause that
server or client  to perform an out-of-bounds read, usually resulting
in a crash.

Backported from:
8e20499629
2198b3a55d

* CVE: CVE-2017-3731

Upstream-status: Backport

(From OE-Core rev: 1fe1cb3e6e03b4f7f0d30b2b67edc8809a18fe70)

Signed-off-by: Alexandru Moise <alexandru.moise@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
Sona Sarmadi
a2f06ef254 libx11: CVE-2016-7943
The XListFonts function in X.org libX11 before 1.6.4 might allow
remote X servers to gain privileges via vectors involving length
fields, which trigger out-of-bounds write operations.

References:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7943
https://lists.x.org/archives/xorg-announce/2016-October/002720.html

Upstream patch:
https://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=8c29f1607a31dac0911e45a0dd3d74173822b3c9

(From OE-Core rev: d627e5bd50f66275cb3a77036ea3376a6f1e9a96)

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
Sona Sarmadi
eed433faba libX11: CVE-2016-7942
The XGetImage function in X.org libX11 before 1.6.4 might allow remote X
servers to gain privileges via vectors involving image type and geometry,
which triggers out-of-bounds read operations.

References
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7942
Upstream patch
https://cgit.freedesktop.org/xorg/lib/libX11/commit/?id=8ea762f94f4c942d898fdeb590a1630c83235c17

(From OE-Core rev: 6d4421301a54c26e390fa943805574ced6e18c3a)

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
Sona Sarmadi
4f991d93f6 libXrandr: fix for CVE-2016-7947 and CVE-2016-7948
CVE-2016-7947
Insufficient validation of server responses result in Integer overflows

CVE-2016-7948
Insufficient validation of server responses result in various data mishandlings

References:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7947
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7948
https://lists.x.org/archives/xorg-announce/2016-October/002720.html

Upstream patch for both CVEs:
https://cgit.freedesktop.org/xorg/lib/libXrandr/commit/?id=a0df3e1c7728205e5c7650b2e6dce684139254a6

(From OE-Core rev: 1c293e889f6eeae36f8f6ddd9676c65d613ad0fc)

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
Sona Sarmadi
b45822fe66 libxrender: CVE-2016-7949
Insufficient validation of server responses results
in overflow of previously reserved memory

Upstream patch:
https://cgit.freedesktop.org/xorg/lib/libXrender/commit/?id=9362c7ddd1af3b168953d0737877bc52d79c94f4

External References:
https://lists.x.org/archives/xorg-announce/2016-October/002720.html
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2016-7949

(From OE-Core rev: 87ffd7ce2e8ece8b44ff3f1c219a74b3590cf14b)

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
David Vincent
7cf454e23c classes: Fix alternatives and rc.d ordering
When using an alternative as an initscript, the ordering between
update-rc.d and update-alternatives tasks during prerm and postinst
tasks must always be the following in order to work:
  * prerm:
    - stop daemon
    - remove alternative

  * postinst:
    - add alternative
    - start daemon

This patchset adds comments to the scripts generated by both classes and
organize the generated sections based on those comments.

[YOCTO #10433]

(From OE-Core rev: b0c70bef015f1b2a30556a5db5e255592d5bf316)

Signed-off-by: David Vincent <freesilicon@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
(cherry picked from commit aa87b1a4dcc14e4dfe719b6c55045c5662bc59c2)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-08 12:00:21 +00:00
Paul Eggleton
5bdf7c980b bitbake: tinfoil: clean environment when starting up cooker
During normal bitbake execution, the environment is cleaned of variables
not on a whitelist while starting up cooker, and then restored
afterwards. Prior to the tinfoil2 rework in master we were taking a
number of shortcuts within tinfoil and one of those was not doing this
environment cleaning. However, prior to OE-Core rev
3d39ca5c91dbb62fb43199f916bd390cd6212e3d we didn't have any code (as far
as I'm aware) that was affected by this shortcut, hence why this wasn't
an issue up to now.

The result is the following error when attempting to run "devtool build"
in the eSDK, as CCACHE_PATH is allowed through from the eSDK's
environment setup script:

----------- snip -----------
ccache: error: Could not find compiler "gcc" in PATH
...
subprocess.CalledProcessError: Command 'gcc  --version' returned
non-zero exit status 1
----------- snip -----------

We can fix this by simply doing the environment filtering while we are
starting up cooker, thus the environment when uninative.bbclass comes to
do the gcc version check it is not affected by CCACHE_PATH or other
variables in the external environment that should be filtered out.

For clarity, this patch is only applicable to the bitbake 1.32 branch
as used for the OE-Core morty branch - master uses the reworked
tinfoil2 and doesn't need this fix.

Fixes [YOCTO #10961].

(Bitbake rev: a240f5ff71092cb209c44a071cd6fa07756ccfa0)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:52:19 +00:00
Richard Purdie
1371bb4c43 bitbake: bitbake-worker: Handle cooker/worker IO deadlocking
I noiced builds where tasks seemed to be taking a surprisingly long time.
When I looked at the output of top/pstree, these tasks were no longer
running despite being listed in knotty. Some were in D/Z state waiting for
their exit code to be collected, others were simply not present at all.

strace showed communication problems between the worker and cooker, each
was trying to write to the other and nearly deadlocking. Eventually, timeouts
would allow them to echange 64kb of data but this was only happening every
few seconds.

Whilst this particularly affected builds on machines with large numbers
of cores (and hence highly parallal task execution) and in cases where
I had a lot of debug enabled, this situation is clearly bad in general.

This patch introduces a thread to the worker which is used to write data
back to cooker. This means that the deadlock can't occur and data flows
much more freely and effectively.

(Bitbake rev: f48befe1163147b02a9926ee38af0f7258a477e0)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:52:19 +00:00
Scott Rifenbark
e732dfb8df yocto-project-qs, poky.ent: Added "pexpect" to essential packages
Fixes [YOCTO #10889]

Missing this package.  Speculation is that this package was
part of the Python 2.7 stuff but not Python 3.  So, adding it
clears the issue up.

(From yocto-docs rev: fc6bfab923f18a8ec91e29fed2404690d0afeb5d)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Andreas Müller
62175510dc nspr: set correct version in pkg-config file
while we are at it clean up sed

(From OE-Core rev: 69e9f7ec8ba8649784a27e9c7dc7a6987a53c22e)

(From OE-Core rev: cb4f5ecf32006192baaf41218a3d7b43ca1c2951)

(From OE-Core rev: 79f821fb6c1b425ca5cb5e6db360c2743d6c989e)

Signed-off-by: Andreas Müller <schnitzeltony@googlemail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Denys Dmytriyenko
f2ff6a40c4 attr/ea-acl: pass --disable-gettext when USE_NLS=no
Fixes following error in configure:
  FATAL ERROR: msgfmt does not seem to be installed.
  attr cannot be built without a working gettext installation.

(From OE-Core rev: 85e087d9b323ad87c59900f01aad751c9c7a9e3a)

Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>

(From OE-Core rev: d044fad8a0ac5d57deb88b25106f3a39cb7c1636)

Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Denys Dmytriyenko
28b0f21342 linux-dtb: strip DTB extension properly in postinst/postrm
The use of awk -F "." in do_install/do_deploy to strip filename extension
was deprecated long time ago in 72980d5bb465f0640ed451d1ebb9c5d2a210ad0c.

Make a similar change in postinst/postrm to properly use basename command.

Otherwise DTB files that contain dots in the name result in broken symlinks
that point to non-existent truncated files.

(From OE-Core rev: ed0f9cf63cb1226f9d92377e13ef63e36a95d29d)

Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>

(From OE-Core rev: 40c2addf0f0ee16b1c1334cf00f1490ffeaac475)

Signed-off-by: Denys Dmytriyenko <denys@ti.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Sona Sarmadi
6e43936704 libxtst: 1.2.2 -> 1.2.3
Upgrade libxtst from 1.2.2 to 1.2.3 to address:
Out of Bounds Write Denial of Service Vulnerability, CVE-2016-7951

References:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7951
https://cgit.freedesktop.org/xorg/lib/libXtst/commit/?id=9556ad67af3129ec4a7a4f4b54a0d59701beeae3

(From OE-Core rev: 02a0dd90c3f3b1fc6ebddc17feb824d11848b2a7)

Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Manjukumar Matha
314c727daa binutils-2.27.inc: Fix alignment frags for aarch64
There was bug with alignment frags for aarch64 in binutils. This is fixed in
master of binutils. This patch backports the fix to binutils 2.27 version.

(From OE-Core rev: f6f87019073d4f3caa7766aca89faa6781690fba)

(From OE-Core rev: c2dcf53587957244e231e1489efa75062a7ceacc)

Signed-off-by: Manjukumar Matha <manjukumar.harthikote-matha@xilinx.com>
Signed-off-by: Nathan Rossi <nathan@nathanrossi.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-02-03 09:51:32 +00:00
Ed Bartosh
a3fa5ce876 populate_sdk_ext: whitelist do_package tasks
With enabled SSTATE_MIRRORS sstate code expects mirrors to
contain entries for all tasks, which is not the case for ext
installer as it uses reduced sstate cache.

Added do_package tasks to BB_SETSCENE_ENFORCE_WHITELIST to prevent
installer failing with ERROR: Sstate artifact unavailable

[YOCTO #10832]

(From OE-Core rev: 2ed46ada4b8e496493835e84b36f7e9c367f59d2)

(From OE-Core rev: eb2fc2cd9081a4533ed30fe81c9f491b06cc5ae1)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-12 17:52:04 +00:00
Ed Bartosh
fd30939f5f populate_sdk_ext: fix working with uninative sstate
Mapped uninative sstate directories to make ext SDK installer to
use them when it's run on systems with gcc version different from
gcc version used to build installer.

[YOCTO #10832]

(From OE-Core rev: fb945c0fd2e66d70461e6cf2e602020eeabe32f7)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-12 17:52:04 +00:00
Joshua Lock
e0b862b68c zlib: update SRC_URI to fix fetching
Upstream have removed the file from zlib.net as a new version has
been released, switch to fetching from the official sourceforge
mirror.

[YOCTO #10879]

(From OE-Core rev: bb99e4a620efd59556539c156cd98ea23aae74c8)

(From OE-Core rev: b7599330f1d629384e16a5fbeffc1a65c1555667)

Signed-off-by: Joshua Lock <joshua.g.lock@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-12 17:52:04 +00:00
Richard Purdie
4b8ddc4322 build-appliance-image: Update to morty head revision
(From OE-Core rev: ae3513b8e752d0dc1757fbfc681f644a3f2855b0)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:26:52 +00:00
Richard Purdie
ae1e127566 Bump version for 2.2.1 morty release
(From meta-yocto rev: 6602215d67cf5d75752e2156a79ddab69a400bee)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:26:30 +00:00
Scott Rifenbark
a9e1475efc documentation: Prepare for 2.2.1 release
* poky.ent - changed variables appropriately for 2.2.1
 * <manual> - updated the manual revision tables to have a new
   2.2.1 entry indicating a "January 2017" release
 * mega-manual.sed - Updated the "2.2" string to "2.2.1" so
   links will work.

(From yocto-docs rev: 20eeccff9fdad25f7b21aa6326999deb3d58abc4)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
25032be4a3 dev-manual: Added cross-reference for tool-chain installation.
(From yocto-docs rev: 9b0be1e92eca1256cc2578b807f33e91fa0ad3b2)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
1b3d0e5168 dev-manual: Updated "Building an Initial RAM Filesystem (initramfs) Image" section
Fixes [YOCTO #7096]

Applied a couple review comments to the section to clarify where
to set key variables.  Also fixed an incorrect variable name used
to specify the *.cpio file.

(From yocto-docs rev: 1ef9bb89057be46878a70c558268b5ace43967f8)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Martin Vuille
0a94b71878 dev-manual: Fixed "recipetool create" example
Fixes [YOCTO #10763]

The final example in the section describing how to create
the base recipe using receipetool create was wrong.  I updated
it to use the -d option in addition to the -o opetion.  I also
changed the description to match appropriately.

(From yocto-docs rev: 749970f4394af3855751c776689b7002232f2d13)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
1e51b7173a dev-manual, ref-manual: Created new section on initramfs
Fixes [YOCTO #7096]

We did not document how to create an initramfs image to be included
with a kernel build.  Various variables sort of inferred the
knowledge.  I created a new section in the "Common Tasks" section
of the dev-manual that describes how to create an initramfs image.

Also, I updated the kernel.bbclass reference section to point back
to the new "how-to" section.

Finally, I also created a bunch of cross-reference links from various
related variables back to the new "how-to" section.

(From yocto-docs rev: a14e550494641c46ac2518632cbf251e07d459fd)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
5068f2c960 ref-manual, dev-manual: Removed term "wic-partitioned"
This term was incorrect and I have replaced it with the
term "partitioned."

(From yocto-docs rev: af1bf889bf862b1bc861de72888a82e25997ab71)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
ba8fc212de dev-manual: Updated to the "Creating Partitioned Images" section
new information on how wic works

(From yocto-docs rev: c5bfbba2bc810eb1ff8825b66aa1397cfeed8ce1)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
ac6773117a ref-manual: Added WKS_FILE description for new variable
This new variable points to the location of the wics kickstart
file.

(From yocto-docs rev: 6d9a7220ed41c8a512eccbad0ae170072d40fc6f)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Scott Rifenbark
13d9371e40 sdk-manual: Added note about nullpointer error for launch eclipse
Fixes [YOCTO #10714]

Apparently there is some issues with GTK3 libraries for the Mars
Eclipse version.  The note provides a workaround that requires
editing the eclipse.ini file.

(From yocto-docs rev: 89ace71c6d9d3a9db84bb9bb2b2abe4779a516f6)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:23:10 +00:00
Kevin Hao
13783cce0b meta-yocto-bsp: bump to the latest linux stable kernel for the non-x86 BSPs
Boot test for all these boards.

(From meta-yocto rev: bfabbe8ef170be5c9c5218612dddb98e0f332891)

(From meta-yocto rev: 5344fde92a6a4d283d8f38beb93ee14c3337e789)

Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Juro Bystricky
e0d8921bf0 edgerouter.py: avoid python3 exception
This fixes an error such as:

Exception: File "/master/poky/meta-yocto-bsp/lib/oeqa/controllers/edgeroutertarget.py", line 47
    self.image_fstype = self.get_image_fstype(d)
TabError: inconsistent use of tabs and spaces in indentation

(From meta-yocto rev: 5ff5dc2767dfef93c314e7465a52ca2dce553604)

(From meta-yocto rev: d1c50ea67f53b5fa2618b460efe4cc879d7cee0c)

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Alejandro Hernandez
61d424fbb3 linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.8
Updates to Linux 4.8.12
- Includes CVE-2016-8655

(From meta-yocto rev: cccbd2d315a69befd090744af095e89bdd0e77bb)

(From meta-yocto rev: a931e4468c39df92cde2ad7bb649dafcd006fba2)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Alejandro Hernandez
b50444c90e linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.4
Updates to Linux 4.4.36
- Includes CVE-2016-8655

(From meta-yocto rev: 95bc86ba1bb33ef2e6808fa7d080c07904073daf)

(From meta-yocto rev: 5e9c0edbfb8cf5a1ad09c6254e432fe27f182fd1)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Alejandro Hernandez
11cc61020e linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.1
Updates to Linux 4.1.36
- Includes CVE-2016-8655

(From meta-yocto rev: 4966f0daa0ae91bd2c1329b4a5434d0fb0c7f477)

(From meta-yocto rev: 6ca9e9d4da1522c9e10c2c1104e5ba3c371d4cb9)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Kevin Hao
a81ec4c00f meta-yocto-bsp: bump to the latest stable linux kernel for the non-x86 BSPs
Boot test for all these boards.

(From meta-yocto rev: e3e35cf4d251dbac5d87fb8f48b7e0a5babb9b1b)

(From meta-yocto rev: 0c4dd1340e8a2f62e46c52f797c1b80ae9605ccf)

Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Richard Purdie
84b3a5ac35 bitbake: cookerdata: Convert multiconfig to use BB_CURRENT_MC
People are struggling with multiconfig as the point the conf file
is injected into the data store is not what people expect. We can't
really use a post config since that is too late and we can't really
use a pre config file since that is too early. In OE terms, we need
something right around the local.conf point so it behaves in a similar
way.

A way to handle this is to set the new variable BB_CURRENT_MC to be the
currently selected multiconfig, then the metadata itself can choose
when to inject the approriate configuration.

(Bitbake rev: 1469828fa747da0aaaa3e964954ff17f2b3180fa)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Richard Purdie
7bab6ffc45 bitbake: runqueue: Only start fakeroot workers when needed
Fakeroot workers usually have dependencies that need to be ready before they
can be started. Starting them as a block therefore doesn't work as the
dependencies may or may not have been built. Therefore start the multiconfig
fakeworkers individually upon demand.

[YOCTO #10344]

(Bitbake rev: ac5ea74152b011256209c8b5664216f290b123e8)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:47 +00:00
Richard Purdie
6b49da40e7 bitbake: runqueue: Ensure setscene tasks with overlapping stamps don't parallel execute
In multiconfig, mutliple tasks can execute which share the same stamp file. These
must not execute in parallel, the idea is the first should execute, the subsequent
ones should see a valid stamp and get skipped.

The normal task execution code has stamps code to handle this, this adds similar
code to the setscene execute() function to handle the issue there too.

(Bitbake rev: df8408a6b54fc908d4de81529b34477b8924d181)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
4bcf8babc4 bitbake: runqueue: Fix setscene issues with multiconfig
setscene was being entirelu skipped for multiconfig variants as the tasks
were simply not being spotted. If the default config was also being built
it masked the problem. When this was fixed by using taskfn instead of fn
in lookups against dataCache, several other instances of this problem were
highlighted.

This goes through and corrects the setscene code to correclty use taskfn
instead of fn in the appropriate places meaning setscene tasks for multiconfig
now work correctly.

(Bitbake rev: a5d81eefe9106f2080001b7313e2b15ab21ea55b)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
ba5ee79aba bitbake: siggen: Fix clean_basepath to work with multiconfig
Tasknames can now start with "multiconfig:" which broke the virtual: comparison code and
lead to unpredictable checksums with nativesdk recipes. This adds in handling for
the new additional prefix which unbreaks nativesdk builds when using multiconfig.

(Bitbake rev: 0ca6b8438624d892ee7ef3b42df0024604b64567)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
f94e71c40a bitbake: build/uihelper: Show better information about multiconfig tasks on UI
Currently the UI shows X is building, possibly multiple times but doesn't
say which of the multilibs that might be. This adds a prefix to the task
name so the mulitconfig being built can be identified.

(Bitbake rev: dfb775c67a96a79f3b85104870c0ade46ef2a9ea)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
30259219ca bitbake: runqueue: Ensure pseudo executes from the correct place (use the right datastore with multiconfig)
The location of the fakeroot command and the various environmental values need
to be taken from the right multiconfig datastore, not the shared one. This
patch ensures the right one is used for cases like a split TMPDIR.

[YOCTO #10344]

(Bitbake rev: c241f16670cada2cdf45ecddb4961e16edb83486)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
86f91f680a bitbake: bitbake: cooker: Handle inofity queue overflows more gracefully
If many files change and the inotify queue overflows, rather than print
a traceback, invalidate the caches and warn the user.

[YOCTO #10676]

(Bitbake rev: 058f8517c041b80e8b591ad7d34a68281b2d03fc)

(Bitbake rev: 4fafb6c6d261de78dd1bc3824a1389d191b70321)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
e171e9a088 bitbake: bitbake: cooker: Fix world taskgraph generation issue
The processing of the "do_" prefix to tasks is currently inconsistent
and has resulted in "bitbake world -g" being broken as task prefixes
don't get handled correctly.

Make the "do_" task prefix handling consistent through various codepaths.

[YOCTO #10651]

(Bitbake rev: 3d7186353e804c9410096c408bc337a98c8b33fe)

(Bitbake rev: 100439e715841ecfd6460d59cd51c831184b328d)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
a411abf823 bitbake: bitbake: utils: Avoid traceback errors
Avoid errors like:

ERROR: Exception handler error: 'NoneType' object has no attribute 'decode'

(Bitbake rev: 1aeb45abe56061f044c2347889c191d5256ff21f)

(Bitbake rev: 1f08fe503b484d4cf5e093f9e3e4c9bbe0be4eda)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
6a3f93a377 libgcc-common: Don't apply symlinks for nativesdk
nativesdk-libgcc doesn't need a symlink into the target space and if we do this
sstate installation of the recipe can fail depending on whether it races with
the cross-canadian toolchains.

(From OE-Core rev: b2c1e1fe4221862e0dbf5d08960f0d0228e47c72)

(From OE-Core rev: 62012e81c6f7aaad5d9c5e8bec2e2417433572e3)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
b4f432e390 bitbake.conf: Add inclusion of BB_CURRENT_MC.conf after local.conf
People are strugling with multiconfig as the up front inclusion of the
configuration file doesn't do what people expect. The only way to meet
user expectations is to include the file immediately after local.conf.

We add BB_CURRENT_MC to bitbake so that the metadata can determine when
to include the extra configuration.

(From OE-Core rev: a6a3894fb2cb2097d2404b8b8cb2b85df595cfa9)

(From OE-Core rev: 378ba0c92172ed7850ec1b0eb2971afb0dae427b)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Richard Purdie
6f65543778 uninative: Parameterise the use of STAGING_DIR
This means that a user can change TMPDIR in a multiconfig situation
and still only have one path to the uninative setup. Without this change
its not possile to make such a setup work.

(From OE-Core rev: 779422c5458f5f643b3a4a0dedaa4d9ad709367a)

(From OE-Core rev: f50547fb9d70a8ae079380c25e697da3d2c2b181)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Ed Bartosh
124df4ee35 selftest: wic: fix test_qemu
Setting WKS_FILE variable in qemux86-64 made wic test to
use wrong wks file to produce an image and resulted in
test_qemu failure.

Used conditional assignment in qemux86-64 and explicitly
set WKS_FILE in wic testing suite to make the suite to use
wic-image-minimal.wsk. This should fix test_qemu failure.

(From OE-Core rev: 3bca4d18c2712e3b154bacfb917f0a749ebaddeb)

(From OE-Core rev: bda4e3cceda2205a0a5d916ef5b674df560d43f9)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Ross Burton
6c5a52ca8f utils: Always use datastore's PATH for host_gcc_version
BUILD_CC may reference something like ccache and expect this to come from
ccache-native, we at least have some selftests which assume this. Modify the
code to use PATH when runnig BUILD_CC to ensure the tests continue to work
as expected.

(From OE-Core rev: f3e753372baac43d0921186340cf260df056de20)

(From OE-Core rev: e7ec3228d9a2f40165b60f273205c17438b2c9bb)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>

Hand applied and used d.getVar(True)
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Jackie Huang
51e2f226bd valgrind: make ld-XXX.so strlen intercept optional
Hack: Depending on how glibc was compiled (e.g. optimised
for size or built with _FORTIFY_SOURCE enabled) the strlen
symbol might not be found in ld-XXX.so. Therefore although
we should still try to intercept it, don't make it mandatory
to do so.

(From OE-Core rev: 84ec50e587e7464b260b1b189659b93b6dab0ef6)

(From OE-Core rev: 850735191c131d7baab72e7df6292b189ea56801)

Signed-off-by: Jackie Huang <jackie.huang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Ed Bartosh
8108c47740 uninative: rebuild uninative for gcc 4.8 and 4.9
Some c++ libraries fail to build if uninative is built
with gcc 5.x and host gcc version is either 4.8 or 4.9.

The issue should be solved by making separate uninative sstate
directory structure sstate-cache/universal-<gcc version> for host gcc
versions 4.8 and 4.9. This causes rebuilds of uninative if host gcc
is either 4.8 or 4.9 and it doesn't match gcc version used to build
uninative.

[YOCTO #10441]

(From OE-Core rev: d36f41e5658bbbb6080ee833027879c119edf3e0)

(From OE-Core rev: 3d39ca5c91dbb62fb43199f916bd390cd6212e3d)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Andrej Valek
c8f4fb15de libxml2: Fix more NULL pointer derefs
The NULL pointer dereferencing could produced some
security problems.
This is a preventive security fix.

(From OE-Core rev: 8f3008114d5000a0865f50833db7c3a3f9808601)

(From OE-Core rev: 401d552f9e4ed3341e42864e566dddb2b26019dc)

Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Pascal Bach <pascal.bach@siemens.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Andrej Valek
359189b6e6 libxml2: fix CVE-2016-4658 Disallow namespace nodes in XPointer points and ranges
Namespace nodes must be copied to avoid use-after-free errors.
But they don't necessarily have a physical representation in a
document, so simply disallow them in XPointer ranges.

(From OE-Core rev: 00e928bd1c2aed9caeaf9e411743805d2139a023)

(From OE-Core rev: cf810d5cc17cb6b9f53d21a404c89afe372accb7)

Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Pascal Bach <pascal.bach@siemens.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Andrej Valek
5ba779d5ab libxml2: Necessary changes before fixing CVE-2016-5131
xpath:
 - Check for errors after evaluating first operand.
 - Add sanity check for empty stack.
 - Include comparation in changes from xmlXPathCmpNodesExt to xmlXPathCmpNodes

(From OE-Core rev: 96ef568f75dded56a2123b63dcc8b443f796afe0)

(From OE-Core rev: 68b0f3a0bf8dfdf49be4aed1745a7f50662c555d)

Signed-off-by: Andrej Valek <andrej.valek@siemens.com>
Signed-off-by: Pascal Bach <pascal.bach@siemens.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:46 +00:00
Paul Eggleton
41e8df8228 lib/oe/rootfs: fix log_check warnings being printed twice with RPM packaging
We were calling _log_check() in the RPM-specific rootfs class as well as
in the base class; this is unnecessary and resulted in any errors/warnings
generated during the actual package installation time triggering two warnings
instead of one. Drop the call from RpmRootfs._create() to fix this.

(From OE-Core rev: 541c56d755ba0354297673e857628026ad9e4df2)

(From OE-Core rev: 9654a6a238a44ed1025a45e4ad1cb779a8684344)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Armin Kuster
baf73313b3 libtiff: Update to 4.0.7
Major changes:
The libtiff tools bmp2tiff, gif2tiff, ras2tiff, sgi2tiff, sgisv, and ycbcr are completely removed from the distribution, used for demos.

CVEs fixed:
CVE-2016-9297
CVE-2016-9448
CVE-2016-9273
CVE-2014-8127
CVE-2016-3658
CVE-2016-5875
CVE-2016-5652
CVE-2016-3632

plus more that are not identified in the changelog.

removed patches integrated into update.
more info: http://libtiff.maptools.org/v4.0.7.html

(From OE-Core rev: 9945cbccc4c737c84ad441773061acbf90c7baed)

(From OE-Core rev: 009b330591b27bd14d4c8ceb767c78fd7eb924fd)

Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
985beaaa13 kernel-yocto: explicitly trap subcommand errors
To trap errors and halt processing, do_kernel_metadata was recently
switched to exit on any non zero return code. While the concept is
sound, there are subcommands that have legitimate non-zero return
codes.

Instead of removing set +e, we'll explicitly check the return code
of the commands that can error, and throw a bbfatal to alert the
user.

(From OE-Core rev: a4705e62d0973c290011fc0d250501d358b659e8)

(From OE-Core rev: a4888a63620fa05e1399355d9e20c2da586efb4c)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
c5489cb14a linux-yocto/4.8: update to -rt7
Updating to the latest 4.8-rt

(From OE-Core rev: 9f4565a308be55c1bf11706041c0565d48bda4f4)

(From OE-Core rev: d7ca7a37c8a5f8baefadc44bdfc1a697d2fe4616)

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Yuanjie Huang
80d90725f5 glibc: Enable backtrace from abort on ARM
ARM stack frames for abort and raise were limited to the the actual
abort and raise call, such as:

Obtained 4 stack frames.
./test-app(print_trace+0x1c) [0x10a08]
./test-app() [0x10b3c]
/lib/libc.so.6(__default_sa_restorer+0) [0x4adae1e0]
/lib/libc.so.6(gsignal+0xa0) [0x4adacf74]

This is not terribly useful when trying to figure out what function
may have called called the abort, especially when using pthreads.

After the change the trace would now look like:

Obtained 8 stack frames.
./test-app(print_trace+0x1c) [0x10a08]
./test-app() [0x10b3c]
/lib/libc.so.6(__default_sa_restorer+0) [0x4befe1e0]
/lib/libc.so.6(gsignal+0xa0) [0x4befcf74]
/lib/libc.so.6(abort+0x134) [0x4befe358]
./test-app(dummy_function+0x50) [0x10adc]
./test-app(main+0xd4) [0x10c24]
/lib/libc.so.6(__libc_start_main+0x114) [0x4bee7a58]

(From OE-Core rev: 93bf8713d8e13c278543baea94fb8dad0cb80e49)

(From OE-Core rev: b0e6a6048fa09dceac78bf8c46d484690ff5b098)

Signed-off-by: Yuanjie Huang <yuanjie.huang@windriver.com>
Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Chen Qi
389d0a02d7 Use weak assignment for SERIAL_CONSOLES in qemu configuration files
Use weak assignment for SERIAL_CONSOLES in qemu configuration files so that
the value could serve as a default value and could be easily overridden in
configuration files like local.conf.

When using the default value for SERIAL_CONSOLES in qemux86-64,we would have
annoying messages on console complaining about respawning getty on ttyS1.
Although the value is set by purpose, at least we need to provide an easy way
to override it.

(From OE-Core rev: 5f060b66162c41a295995947b918253450870117)

(From OE-Core rev: 5a19335f0f1d763a066a8c9ead23bb332e229f93)

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Ross Burton
ea584f108c archiver: don't change directory when generating tarball
There's no need to chdir() as tarfile.add() can be told what name to use in the
archive.

(From OE-Core rev: d0b282bce34db44dde4dd7f53a64dfaafe6789de)

(From OE-Core rev: d637d5f02be4eab26cfab7352a8ea584fb1f7e4d)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Awais Belal
29184b22d7 grub2: fix some quirks and div by zero
Rather than erroring out on a single attempt while
terminating EFI services, make a few retries because
such quirks are found in a few implementations.
Also fix a div by zero issue in the same framework
which causes an infinite reboot on the target.
Both patches included here are backports.

(From OE-Core rev: 5e6ac806bd9b8bf885ef1e88484e91e4cdaaa69a)

(From OE-Core rev: dbe597b317067362e7acddbefd0d6768f6a44e8c)

Signed-off-by: Awais Belal <awais_belal@mentor.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Alessio Igor Bogani
0533d4e8ec wic: Create a logical partition only when it is really mandatory
Don't worth bother with logical partition on MBR partition type (aka
msdos) if disk image generated by wic should have 4 partitions.

(From OE-Core rev: 36a558fbdc96094626e7de1a3510691e30885368)

(From OE-Core rev: 98a3e096eaa6cfdf1532c7c03c57222ae8cd6533)

Signed-off-by: Alessio Igor Bogani <alessio.bogani@elettra.eu>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Chen Qi
2cfd1582df libarchive: fix ALTERNATIVE_PRIORITY to avoid conflict
'tar' utility from tar and bsdtar has the same alternative priority.
'cpio' utility from cpio and bsdcpio has the same alternative priority.

Lower the ALTERNATIVE_PRIORITY to avoid conflict.

(From OE-Core rev: 9a59ff628771b586666999d44923968a6bc58956)

(From OE-Core rev: 773ea033e973abd2b97c62b8095d7142c020ad24)

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Ross Burton
6011f5658d cve-check: allow recipes to override the product name
Add a new variable CVE_PRODUCT for the product name to look up in the NVD
database.  Default this to BPN, but allow recipes such as tiff (which is libtiff
in NVD) to override it.

(From OE-Core rev: ba330051570a4c991885ee726cb187e0c911bd4f)

(From OE-Core rev: bee636b759feafba544e95d6355c52eb85e4ba72)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Ross Burton
b9879ad3f9 curl: set CVE_PRODUCT
This is 'libcurl' in NVD.

(From OE-Core rev: f5381da49ac781ef017a1b9816c00b512ca9c7c2)

(From OE-Core rev: ae9910f08207d0bb1c57e72e4463768bc0445e48)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Ross Burton
1c8b9df38c tiff: set CVE_PRODUCT
This is 'libtiff' in NVD.

(From OE-Core rev: 0c8d1523f3ad0ada2d1b8f9abffbc2b898a744ca)

(From OE-Core rev: e89a617a64e25036b4f172692c7a461b5291cabb)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Juro Bystricky
1933b492ca targetloader.py: drop test for ClassType
ClassType was removed from python3.
The code testing for ClassType kept throwing AttributeError exceptions:

    module 'types' has no attribute 'ClassType'

The exceptions prevented loading of any dynamically resolved target
controllers.

(From OE-Core rev: d62f18c39bc0ed3b0f5ac8465b393c15f2143ecf)

(From OE-Core rev: 6258471b7077839519898d537b99dce0a0fc8aa4)

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
da3332f2e2 linux-yocto/4.x: CVE-2016-8655
Backporting upstream commit 84ac726023 [packet: fix race condition in
packet_set_ring] to address CVE-2016-8655

(From OE-Core rev: db7799747b263507427e325638353142ae79403c)

(From OE-Core rev: 9ec9712436080bb08c99d5ac6783383955bb7dc1)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
50cf219c3a linux-yocto-rt/4.4: update to -rt43
After the update to 4.4.36 -rt no longer builds. The fixes for the
issues are found in the v4.4-rt43 release.

(From OE-Core rev: 262fff10ba5cdedbee9ba9ecf00f98dc9159477c)

(From OE-Core rev: 86e24908bb28d4e0ee7defdc64a2efd8eefe37c7)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
c3d06886b7 kern-tools: ensure that no shared directories are used
We need to avoid using shared/common directories for any files that are
part of specific build, since permissions issues in multi user
environments will cause issues.

Integrating the following commit to solve the issue:

   scc: move unused patch queue under output dir

(From OE-Core rev: cad65cc0eef2e06cb5ae08062ffae7a4d43a51ad)

(From OE-Core rev: e57f861496ed07aca8785a53971b34c99a4d64bd)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
5580c222b4 linux-yocto/4.8: update to v4.8.12
shortlog of the changes follow:

   356ccf6d2b0c Linux 4.8.12
   f81c90012f2f scsi: mpt3sas: Unblock device after controller reset
   3de3eebb10fd flow_dissect: call init_default_flow_dissectors() earlier
   7838fbe25a95 mm, oom: stop pre-mature high-order OOM killer invocations
   374ff835e2b6 can: bcm: fix support for CAN FD frames
   7ed8d94b99b3 powerpc/boot: Fix the early OPAL console wrappers
   7cbe9568fa04 powerpc/mm: Fixup kernel read only mapping
   30988ea31783 powerpc: Set missing wakeup bit in LPCR on POWER9
   8d248df485f2 device-dax: fail all private mapping attempts
   f87a483126b5 device-dax: check devm_nsio_enable() return value
   5b08489eba14 xc2028: Fix use-after-free bug properly
   9030deb21f29 X.509: Fix double free in x509_cert_parse() [ver #3]
   0257b7e20c07 mpi: Fix NULL ptr dereference in mpi_powm() [ver #3]
   bdab996a7a9e mmc: sdhci-of-esdhc: fixup PRESENT_STATE read
   0a80bef18a9f parisc: Also flush data TLB in flush_icache_page_asm
   09e35a83cdc9 parisc: Fix race in pci-dma.c
   3cb2bc6fdc54 parisc: Switch to generic sched_clock implementation
   113b60efa37c parisc: Fix races in parisc_setup_cache_timing()
   b2f64572db2e thermal/powerclamp: add back module device table
   6dfe1643b56a perf/x86/intel: Cure bogus unwind from PEBS entries
   403f47ddbf6b perf/core: Fix address filter parser
   c5795c5f682d x86/traps: Ignore high word of regs->cs in early_fixup_exception()
   885bad1e5f32 x86/fpu: Fix invalid FPU ptrace state after execve()
   1a42cd56229b NFSv4.x: hide array-bounds warning
   154c665b2b02 apparmor: fix change_hat not finding hat after policy replacement
   9c15a98542f0 cfg80211: limit scan results cache size
   f204d21ee0b7 tile: avoid using clocksource_cyc2ns with absolute cycle count
   c707019bef62 scsi: mpt3sas: Fix secure erase premature termination
   b33387f6a68d Fix USB CB/CBI storage devices with CONFIG_VMAP_STACK=y
   89a28f3a3c77 USB: serial: ftdi_sio: add support for TI CC3200 LaunchPad
   6476f6530187 USB: serial: cp210x: add ID for the Zone DPMX
   7445ffb75ed5 usb: chipidea: move the lock initialization to core file
   32fe669c8634 KVM: x86: check for pic and ioapic presence before use
   c02d13809180 KVM: x86: fix out-of-bounds accesses of rtc_eoi map
   39b653013527 KVM: x86: drop error recovery in em_jmp_far and em_ret_far
   3c22c81377d4 KVM: x86: fix out-of-bounds access in lapic
   eb060c1a03f7 iommu/vt-d: Fix IOMMU lookup for SR-IOV Virtual Functions
   8b23f16343f6 iommu/vt-d: Fix PASID table allocation
   36bd5bfe4349 Linux 4.8.11
   a9a0027757f8 gpio: pca953x: Fix corruption of other gpios in set_multiple.
   88fce76cf590 gpio: pca953x: Move memcpy into mutex lock for set multiple
   9a7b80894951 netfilter: nft_dynset: fix element timeout for HZ != 1000
   fd4251fa4d09 IB/cm: Mark stale CM id's whenever the mad agent was unregistered
   8ce92be782f8 IB/uverbs: Fix leak of XRC target QPs
   160149299f71 IB/hfi1: Remove incorrect IS_ERR check
   46e47543175b IB/core: Avoid unsigned int overflow in sg_alloc_table
   82c377d05311 IB/mlx5: Fix NULL pointer dereference on debug print
   554e4b69f1bb IB/mlx5: Fix fatal error dispatching
   32091ee63d17 IB/mlx5: Fix memory leak in query device
   21822a5bbddd IB/mlx5: Use cache line size to select CQE stride
   ad886a0e9035 IB/mlx5: Validate requested RQT size
   76a93a6f8dd7 IB/mlx4: Fix create CQ error flow
   4234e6a06f8b IB/mlx4: Check gid_index return value
   fc9275365065 IB/rxe: Clear queue buffer when modifying QP to reset
   3c87b4a8f6d5 IB/rxe: Fix handling of erroneous WR
   c4605a0e9605 IB/rxe: Fix kernel panic in UDP tunnel with GRO and RX checksum
   04d016249998 IB/rxe: Update qp state for user query
   bac1543b764c perf hists: Fix column length on --hierarchy
   4cba876de64d PM / sleep: don't suspend parent when async child suspend_{noirq, late} fails
   2e2c8f0e7502 PM / sleep: fix device reference leak in test_suspend
   fd669bf2a099 uwb: fix device reference leaks
   ab17baeaea91 sunrpc: svc_age_temp_xprts_now should not call setsockopt non-tcp transports
   8c7ea73e3a9b mfd: core: Fix device reference leak in mfd_clone_cell
   545ea4003db9 iwlwifi: mvm: wake the wait queue when the RX sync counter is zero
   8bfaf856695b iwlwifi: mvm: fix d3_test with unified D0/D3 images
   8cdfd32398b5 iwlwifi: mvm: fix netdetect starting/stopping for unified images
   6e3324dc039c iwlwifi: pcie: mark command queue lock with separate lockdep class
   b822907865cc iwlwifi: pcie: fix SPLC structure parsing
   edb60ee4bc65 rtc: omap: Fix selecting external osc
   5f95e68daae3 clk: imx: fix integer overflow in AV PLL round rate
   fec43900c9b7 clk: mmp: mmp2: fix return value check in mmp2_clk_init()
   63465eaf7b2e clk: mmp: pxa168: fix return value check in pxa168_clk_init()
   a42bbd552ded clk: mmp: pxa910: fix return value check in pxa910_clk_init()
   bb6c9ec826be virtio-net: drop legacy features in virtio 1 mode
   899f5426eebf drm/i915: Assume non-DP++ port if dvo_port is HDMI and there's no AUX ch specified in the VBT
   f6920e506992 drm/i915: Refresh that status of MST capable connectors in ->detect()
   56a02a5f60ea drm/amdgpu: Attach exclusive fence to prime exported bo's. (v5)
   3eac4767dd7e powerpc/64: Fix setting of AIL in hypervisor mode
   fc312878ffe3 crypto: caam - do not register AES-XTS mode on LP units
   54f28973e8a5 ARM: dts: imx53-qsb: Fix regulator constraints
   7001b98b9dce ext4: sanity check the block and cluster size at mount time
   56df604296c2 kbuild: Steal gcc's pie from the very beginning
   e14754cb8f0c x86/kexec: add -fno-PIE
   ad4e2f324ade scripts/has-stack-protector: add -fno-PIE
   1c7727d0bca0 kbuild: add -fno-PIE
   20bcbe246933 Disable the __builtin_return_address() warning globally after all
   504b60516ba7 i2c: i2c-mux-pca954x: fix deselect enabling for device-tree
   45244660281c i2c: mux: fix up dependencies
   ce97f5012b6d ALSA: hda - Fix mic regression by ASRock mobo fixup
   23e14ee1abcf ALSA: hda - add a new condition to check if it is thinkpad
   85fcb62a58b2 ALSA: usb-audio: Fix use-after-free of usb_device at disconnect
   e902f10da218 gpio: do not double-check direction on sleeping chips
   b21b327d96bc can: bcm: fix warning in bcm_connect/proc_register
   50e6cd2feff7 mfd: stmpe: Fix RESET regression on STMPE2401
   e015527c6fbd mfd: intel-lpss: Do not put device in reset state on suspend
   8b4d44f46bf2 IB/hfi1: Fix rnr_timer addition
   06eac15f11e0 IB/rdmavt: rdmavt can handle non aligned page maps
   ca720a2b11b4 fuse: fix fuse_write_end() if zero bytes were copied
   de58c50e84e2 genirq: Use irq type from irqdata instead of irqdesc
   8844024c8839 ftrace: Add more checks for FTRACE_FL_DISABLED in processing ip records
   c5d20ce0b459 ftrace: Ignore FTRACE_FL_DISABLED while walking dyn_ftrace records
   f271087fb2ea KVM: arm64: Fix the issues when guest PMCCFILTR is configured
   8d8b37e242de arm64: KVM: pmu: Fix AArch32 cycle counter access
   1cb9b2489e77 KVM: Disable irq while unregistering user notifier
   23555ca21394 KVM: x86: fix missed SRCU usage in kvm_lapic_set_vapic_addr
   f8c74cf95655 x86/cpu/AMD: Fix cpu_llc_id for AMD Fam17h systems

(From OE-Core rev: beb9adb4763a1bbed182503371921e676ccd4ae2)

(From OE-Core rev: a09653cae042c287c109f6891f7abedfddaba828)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:45 +00:00
Bruce Ashfield
a17d78b33c linux-yocto/4.4: update to v4.4.36
shortlog of the changes follow:

   87c6c6ef5b17 Linux 4.4.36
   6eddf5c993dd scsi: mpt3sas: Unblock device after controller reset
   c178e4809df7 flow_dissect: call init_default_flow_dissectors() earlier
   0b7860d6e88c mei: fix return value on disconnection
   bab2f72f70ea mei: me: fix place for kaby point device ids.
   4f13967ecd20 mei: me: disable driver on SPT SPS firmware
   e1049372d7a7 drm/radeon: Ensure vblank interrupt is enabled on DPMS transition to on
   249090830942 mpi: Fix NULL ptr dereference in mpi_powm() [ver #3]
   cd4235a794c0 parisc: Also flush data TLB in flush_icache_page_asm
   7a1ab6a2bf3a parisc: Fix race in pci-dma.c
   e541fd815db9 parisc: Fix races in parisc_setup_cache_timing()
   0c0ddbf7efec NFSv4.x: hide array-bounds warning
   be79d7fa43f9 apparmor: fix change_hat not finding hat after policy replacement
   8316338a201b cfg80211: limit scan results cache size
   4df31626fc08 tile: avoid using clocksource_cyc2ns with absolute cycle count
   ffffc1ed47e7 scsi: mpt3sas: Fix secure erase premature termination
   ab0867dd8bc8 Fix USB CB/CBI storage devices with CONFIG_VMAP_STACK=y
   f3f95f177269 USB: serial: ftdi_sio: add support for TI CC3200 LaunchPad
   1f36db0b397f USB: serial: cp210x: add ID for the Zone DPMX
   55d061bf9d23 usb: chipidea: move the lock initialization to core file
   341f9730c29b KVM: x86: check for pic and ioapic presence before use
   b7f9404d1b48 KVM: x86: drop error recovery in em_jmp_far and em_ret_far
   c091bbddbc5e iommu/vt-d: Fix IOMMU lookup for SR-IOV Virtual Functions
   d88a1bd00cfa iommu/vt-d: Fix PASID table allocation
   0a5b451a53d4 Linux 4.4.35
   1ba7fafae3c2 netfilter: nft_dynset: fix element timeout for HZ != 1000
   698a8dddb8a5 IB/cm: Mark stale CM id's whenever the mad agent was unregistered
   2b026a265a9a IB/uverbs: Fix leak of XRC target QPs
   eba83a85caba IB/core: Avoid unsigned int overflow in sg_alloc_table
   c524185c81d4 IB/mlx5: Fix fatal error dispatching
   734039913373 IB/mlx5: Use cache line size to select CQE stride
   7cf5b7882184 IB/mlx4: Fix create CQ error flow
   41664d7077e9 IB/mlx4: Check gid_index return value
   04c0800c73b2 PM / sleep: don't suspend parent when async child suspend_{noirq, late} fails
   469fcbcb84d8 PM / sleep: fix device reference leak in test_suspend
   680bc27065b9 uwb: fix device reference leaks
   dd214a159de6 mfd: core: Fix device reference leak in mfd_clone_cell
   d2adb5ebec61 iwlwifi: pcie: fix SPLC structure parsing
   1f995573bac8 rtc: omap: Fix selecting external osc
   c8aa3e98c1a8 clk: mmp: mmp2: fix return value check in mmp2_clk_init()
   96576127ffb7 clk: mmp: pxa168: fix return value check in pxa168_clk_init()
   a4709b4582ac clk: mmp: pxa910: fix return value check in pxa910_clk_init()
   d039fc37ec7f drm/amdgpu: Attach exclusive fence to prime exported bo's. (v5)
   96f10a6239a2 crypto: caam - do not register AES-XTS mode on LP units
   454cf79b05c5 ext4: sanity check the block and cluster size at mount time
   147117cf23c0 kbuild: Steal gcc's pie from the very beginning
   e543f094a38a x86/kexec: add -fno-PIE
   3a868dde1824 scripts/has-stack-protector: add -fno-PIE
   f740b5cc39dd kbuild: add -fno-PIE
   936d157fa7ae i2c: mux: fix up dependencies
   4e583b89add6 can: bcm: fix warning in bcm_connect/proc_register
   0c6e0db9686b mfd: intel-lpss: Do not put device in reset state on suspend
   b7321bcc8b1c fuse: fix fuse_write_end() if zero bytes were copied
   d4a774fdb92f KVM: Disable irq while unregistering user notifier
   b689e86c9a8f KVM: x86: fix missed SRCU usage in kvm_lapic_set_vapic_addr
   aea9d760b8ba x86/cpu/AMD: Fix cpu_llc_id for AMD Fam17h systems
   4eb9a8100248 Linux 4.4.34
   b4bbdcef7d90 sparc64: Delete now unused user copy fixup functions.
   cb85910b0d45 sparc64: Delete now unused user copy assembler helpers.
   1c7e17b1c4d6 sparc64: Convert U3copy_{from,to}_user to accurate exception reporting.
   7181969338f8 sparc64: Convert NG2copy_{from,to}_user to accurate exception reporting.
   bfc8be659309 sparc64: Convert NGcopy_{from,to}_user to accurate exception reporting.
   dc3a7a7d2c85 sparc64: Convert NG4copy_{from,to}_user to accurate exception reporting.
   1731d90d8a55 sparc64: Convert U1copy_{from,to}_user to accurate exception reporting.
   8a444c770f6e sparc64: Convert GENcopy_{from,to}_user to accurate exception reporting.
   c718e917b3d3 sparc64: Convert copy_in_user to accurate exception reporting.
   dd8a78b2b6ad sparc64: Prepare to move to more saner user copy exception handling.
   756723ad553d sparc64: Delete __ret_efault.
   f5a69ff7486e sparc64: Handle extremely large kernel TLB range flushes more gracefully.
   d36a1ac49d24 sparc64: Fix illegal relative branches in hypervisor patched TLB cross-call code.
   5d8eb954763d sparc64: Fix instruction count in comment for __hypervisor_flush_tlb_pending.
   217f829ae967 sparc64: Fix illegal relative branches in hypervisor patched TLB code.
   2ba06323db41 sparc64: Handle extremely large kernel TSB range flushes sanely.
   75931800733c sparc: Handle negative offsets in arch_jump_label_transform
   8fd11efa2140 sparc64 mm: Fix base TSB sizing when hugetlb pages are used
   4e90b6880135 sparc: serial: sunhv: fix a double lock bug
   a395f7a66eec sparc: Don't leak context bits into thread->fault_address
   4e772c53ab98 tty: Prevent ldisc drivers from re-using stale tty fields
   225a24ae9733 tcp: take care of truncations done by sk_filter()
   ae9e052a58ef ipv4: use new_gw for redirect neigh lookup
   5c67f9477bb2 net: __skb_flow_dissect() must cap its return value
   b67ed647d135 sock: fix sendmmsg for partial sendmsg
   0650eeb4f187 fib_trie: Correct /proc/net/route off by one error
   3f8857a4971d sctp: assign assoc_id earlier in __sctp_connect
   65d29c185614 ipv6: dccp: add missing bind_conflict to dccp_ipv6_mapped
   99131760a885 ipv6: dccp: fix out of bound access in dccp_v6_err()
   a2df29ed840f dccp: fix out of bound access in dccp_v4_err()
   ad6d0a82016b dccp: do not send reset to already closed sockets
   69a5c7ca2e62 tcp: fix potential memory corruption
   8777977b22c4 ip6_tunnel: Clear IP6CB in ip6tunnel_xmit()
   c5bad811ca4d bgmac: stop clearing DMA receive control register right after it is set
   6e9ca1b61cc8 net: mangle zero checksum in skb_checksum_help()
   ac4c2cf6f57a net: clear sk_err_soft in sk_clone_lock()
   74e53a3a053f dctcp: avoid bogus doubling of cwnd after loss
   86429bd405de Linux 4.4.33
   21cc1a183a9d netfilter: fix namespace handling in nf_log_proc_dostring
   ee5dd6878886 btrfs: qgroup: Prevent qgroup->reserved from going subzero
   ae6d4df4a7a0 mmc: mxs: Initialize the spinlock prior to using it
   ae5b8dbfe6be ASoC: sun4i-codec: return error code instead of NULL when create_card fails
   125e84726d7c ACPI / APEI: Fix incorrect return value of ghes_proc()
   5cd2cd84d573 i40e: fix call of ndo_dflt_bridge_getlink()
   5be7e6b48b21 hwrng: core - Don't use a stack buffer in add_early_randomness()
   ba8580f6cf03 lib/genalloc.c: start search from start of chunk
   c048b6711ed6 mei: bus: fix received data size check in NFC fixup
   19426f065d1e iommu/vt-d: Fix dead-locks in disable_dmar_iommu() path
   f029e7b34f25 iommu/amd: Free domain id when free a domain of struct dma_ops_domain
   f5bb84163704 tty/serial: at91: fix hardware handshake on Atmel platforms
   49163391881a dmaengine: at_xdmac: fix spurious flag status for mem2mem transfers
   fff40ee4d224 drm/i915: Respect alternate_ddc_pin for all DDI ports
   d7b0055e5566 KVM: MIPS: Precalculate MMIO load resume PC
   d24587404922 scsi: mpt3sas: Fix for block device of raid exists even after deleting raid disk
   6e897d034d4c scsi: qla2xxx: Fix scsi scan hang triggered if adapter fails during init
   29cf142cefed iio: orientation: hid-sensor-rotation: Add PM function (fix non working driver)
   caff14e99c63 iio: hid-sensors: Increase the precision of scale to fix wrong reading interpretation.
   dbbc5e6bcf36 clk: qoriq: Don't allow CPU clocks higher than starting value
   2c5cdadeab5d toshiba-wmi: Fix loading the driver on non Toshiba laptops
   f523deedff82 drbd: Fix kernel_sendmsg() usage - potential NULL deref
   f1de32232db3 usb: gadget: u_ether: remove interrupt throttling
   0ab4186bf238 USB: cdc-acm: fix TIOCMIWAIT
   290ffd550e34 staging: nvec: remove managed resource from PS2 driver
   4aa859ea591e Revert "staging: nvec: ps2: change serio type to passthrough"
   729eb8d9f7b7 drivers: staging: nvec: remove bogus reset command for PS/2 interface
   6bba8c37ceed staging: iio: ad5933: avoid uninitialized variable in error case
   a98e483ca784 pinctrl: cherryview: Prevent possible interrupt storm on resume
   126d0a2fe878 pinctrl: cherryview: Serialize register access in suspend/resume
   c45bfaa9211e ARC: timer: rtc: implement read loop in "C" vs. inline asm
   3b21a0b468a3 s390/hypfs: Use get_free_page() instead of kmalloc to ensure page alignment
   e835220ed25f coredump: fix unfreezable coredumping task
   5c54f79ad234 swapfile: fix memory corruption via malformed swapfile
   2f7496c48a7b dib0700: fix nec repeat handling
   a04769029386 ASoC: cs4270: fix DAPM stream name mismatch
   f3155797b91c ALSA: info: Limit the proc text input size
   c1ea2b3c07c6 ALSA: info: Return error for invalid read/write

(From OE-Core rev: 7d8d71ba5bc2dd8884c3f43a8d71a6d399c4e2fe)

(From OE-Core rev: ccca1eda8bb40dc79099d80e0314521aafa9f4aa)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Bruce Ashfield
521b01ab7c linux-yoct/4.1: update to v4.1.36
Shortlog of the changes:

   8576fa45c10e Linux 4.1.36
   39f99860357c kbuild: add -fno-PIE
   bf5d3d296abf firewire: net: fix fragmented datagram_size off-by-one
   c604dec3d5a6 firewire: net: guard against rx buffer overflows
   9fe6256c0020 parisc: Ensure consistent state when switching to kernel stack at syscall entry
   83a474ed7003 ovl: fsync after copy-up
   c0b309f18b01 virtio: console: Unlock vqs while freeing buffers
   4fe9ae4d3fcf md: be careful not lot leak internal curr_resync value into metadata. -- (all)
   e1e5cab9b43c md: sync sync_completed has correct value as recovery finishes.
   97d53c4d89e0 scsi: arcmsr: Send SYNCHRONIZE_CACHE command to firmware
   d207c6603fc6 scsi: scsi_debug: Fix memory leak if LBP enabled and module is unloaded
   169eb57c9e8d drm/radeon/si_dpm: workaround for SI kickers
   c1593e5dcc2a drm/dp/mst: Check peer device type before attempting EDID read
   e5c6bbbcc7be drm/dp/mst: add some defines for logical/physical ports
   dadd5803301f drm/dp/mst: Clear port->pdt when tearing down the i2c adapter
   a2d4bd9c99cc KVM: MIPS: Precalculate MMIO load resume PC
   b05ff0cb0dea KVM: MIPS: Make ERET handle ERL before EXL
   90a107c0b85b drm/radeon: drop register readback in cayman_cp_int_cntl_setup
   9a9a2373142a scsi: megaraid_sas: Fix data integrity failure for JBOD (passthrough) devices
   1b15bd739689 Revert "drm/radeon: fix DP link training issue with second 4K monitor"
   5bc028b10d04 powerpc: Convert cmp to cmpd in idle enter sequence
   00a4335dfaa5 drm/radeon/si_dpm: Limit clocks on HD86xx part
   469bc68e081c drm/radeon/si/dpm: add workaround for for Jet parts
   85a2af9f690a USB: serial: cp210x: fix tiocmget error handling
   0854ce492ec3 Input: i8042 - add XMG C504 to keyboard reset table
   0e9bbbdfe9f8 ALSA: hda - Merge RIRB_PRE_DELAY into CTX_WORKAROUND caps
   02426cf24407 mac80211: discard multicast and 4-addr A-MSDUs
   f065a553f36e ubifs: Fix regression in ubifs_readdir()
   5fdb4fad291f GenWQE: Fix bad page access during abort of resource allocation
   55a2f87cd564 mm/list_lru.c: avoid error-path NULL pointer deref
   52e7b6bd8378 btrfs: fix races on root_log_ctx lists
   9f2d48f0745f vt: clear selection before resizing
   93ec720c6f10 tty: limit terminal size to 4M chars
   ca963122cab2 ALSA: usb-audio: Add quirk for Syntek STK1160
   3dc8f1f0decb KEYS: Fix short sprintf buffer in /proc/keys show function
   1f7ff6f7910e hv: do not lose pending heartbeat vmbus packets
   9662d19bab68 mei: txe: don't clean an unprocessed interrupt cause.
   a64291d578dd ANDROID: binder: Clear binder and cookie when setting handle in flat binder struct
   11924cba404d ANDROID: binder: Add strong ref checks
   39709c84807f dm table: fix missing dm_put_target_type() in dm_table_add_target()
   c91812c8ef76 usb: increase ohci watchdog delay to 275 msec
   51b231bd1a95 arm64: KVM: Take S1 walks into account when determining S2 write faults
   bb21e0295064 arm/arm64: KVM: Handle out-of-RAM cache maintenance as a NOP
   7fbfac87fbf5 USB: serial: fix potential NULL-dereference at probe
   605a6960617f xhci: workaround for hosts missing CAS bit
   c23a6dce1147 xhci: add restart quirk for Intel Wildcatpoint PCH
   4c17f91bb370 kvm: x86: memset whole irq_eoi
   9c5e89d59d56 libxfs: clean up _calc_dquots_per_chunk
   d1375c3e4f2e target: Don't override EXTENDED_COPY xcopy_pt_cmd SCSI status code
   ac49951623e1 target: Re-add missing SCF_ACK_KREF assignment in v4.1.y
   eaf55207fe3b ubifs: Abort readdir upon error
   b9ce8700a2e3 UBIFS: Fix possible memory leak in ubifs_readdir()
   cad1ca2a9485 ubifs: Fix xattr_names length in exit paths
   dfeb7e4f30e9 arm64: percpu: rewrite ll/sc loops in assembly
   3c9c01324032 powerpc/mm: Prevent unlikely crash in copro_calculate_slb()
   c1f5e5f89b99 isofs: Do not return EACCES for unknown filesystems
   b15662c8e266 irqchip/gic-v3-its: Fix entry size mask for GITS_BASER
   af17243fc1b4 arm64: kernel: Init MDCR_EL2 even in the absence of a PMU
   c911b72eaff1 USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7
   59eabe8bb60f memstick: rtsx_usb_ms: Manage runtime PM when accessing the device
   86559fc191ca memstick: rtsx_usb_ms: Runtime resume the device when polling for cards
   a89634cf709b mmc: rtsx_usb_sdmmc: Handle runtime PM while changing the led
   e79c2f2f7b30 mmc: rtsx_usb_sdmmc: Avoid keeping the device runtime resumed when unused
   f125e7f2285c mmc: sdhci: cast unsigned int to unsigned long long to avoid unexpeted error
   517052446f36 usb: gadget: function: u_ether: don't starve tx request queue
   66f38bf99faa ceph: fix error handling in ceph_read_iter
   9e9ca450cd93 irqchip/gicv3: Handle loop timeout proper
   88b6c9f4146a drm/radeon: change vblank_time's calculation method to reduce computational error.
   dcf4c1144f3a jbd2: fix incorrect unlock on j_list_lock
   a3da255ead60 scsi: Fix use-after-free
   8df981058e4f mmc: core: Annotate cmd_hdr as __le32
   7ea3d2e9c6aa x86/mm: Expand the exception table logic to allow new handling options

(From OE-Core rev: 41ab5422d4dc62b6e21ccad975b2a22960d3a44b)

(From OE-Core rev: cf6fd639735709e8216b257ccc0c4a431dec499e)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Bruce Ashfield
87e5e492bc linux-yocto/4.4/4.8: Fix remaining kernel_configcheck warnings in Intel BSPs
Integrating the following meta-data change to remove warnings during
kernel configuration checking:

  bec7e0ace0e5 leds.cfg: Remove CONFIG_LEDS_TRIGGER_CPU
  cc857e64ea34 bsp/intel-quark: Remove bosch-pressure-sensor-i2c
  3198ab25af74 features/i2c: Support I2C_MUX by default

(From OE-Core rev: 2cf5fae50a3b7f232ad667c6c60eaa3f2aafd149)

(From OE-Core rev: 84268e01a48d074f45af8d5e8f36ab9a99505176)

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Bruce Ashfield
9db1372e45 linux-yocto/4.8: aufs warning and ixgbe calltrace
Integrating the following commits to fix aufs/ixgbe issues:

   Author: Liwei Song <liwei.song@windriver.com>
   Date:   Mon Dec 5 00:50:16 2016 -0500

       ixgbe: initialize u64_stats_sync structures early at ixgbe_probe

       Fix the following CallTrace:
       INFO: trying to register non-static key.
       the code is fine but needs lockdep annotation.
       turning off the locking correctness validator.
       CPU: 71 PID: 1 Comm: swapper/0 Not tainted 4.8.8-WR9.0.0.1_standard #11
       Hardware name: Intel Corporation S2600WTT/S2600WTT,
       BIOS GRNDSDP1.86B.0036.R05.1407140519 07/14/2014
        00200086 00200086 eb5e1ab8 c144dd70 00000000 00000000 eb5e1af8 c10af89a
        c1d23de4 eb5e1af8 00000009 eb5d8600 eb5d8638 eb5e1af8 c10b14d8 00000009
        0000000a c1d32911 00000000 00000000 e44c826c eb5d8000 eb5e1b74 c10b214e
       Call Trace:
        [<c144dd70>] dump_stack+0x5f/0x8f
        [<c10af89a>] register_lock_class+0x25a/0x4c0
        [<c10b14d8>] ? check_irq_usage+0x88/0xc0
        [<c10b214e>] __lock_acquire+0x5e/0x17a0
        [<c1abdb9b>] ? _raw_spin_unlock_irqrestore+0x3b/0x70
        [<c10cf14a>] ? rcu_read_lock_sched_held+0x8a/0x90
        [<c10b3c5f>] lock_acquire+0x9f/0x1f0
        [<c1922dcf>] ? dev_get_stats+0x5f/0x110
        [<c176e6b3>] ixgbe_get_stats64+0x113/0x320
        [<c1922dcf>] ? dev_get_stats+0x5f/0x110
        [<c1922dcf>] dev_get_stats+0x5f/0x110
        [<c1ab5415>] rtnl_fill_stats+0x40/0x105
        [<c193dd45>] rtnl_fill_ifinfo+0x4c5/0xd20
        [<c11c5115>] ? __kmalloc_node_track_caller+0x1a5/0x410
        [<c1917487>] ? __kmalloc_reserve.isra.42+0x27/0x80
        [<c191754f>] ? __alloc_skb+0x6f/0x270
        [<c1942291>] rtmsg_ifinfo_build_skb+0x71/0xd0
        [<c194230a>] rtmsg_ifinfo.part.23+0x1a/0x50
        [<c1923dad>] ? call_netdevice_notifiers_info+0x2d/0x60
        [<c194236b>] rtmsg_ifinfo+0x2b/0x40
        [<c192f997>] register_netdevice+0x3d7/0x4d0
        [<c192faa7>] register_netdev+0x17/0x30
        [<c177b83d>] ixgbe_probe+0x118d/0x1610
        [<c1498202>] local_pci_probe+0x32/0x80
        [<c1498172>] ? pci_match_device+0xd2/0x100
        [<c14991e0>] pci_device_probe+0xc0/0x110
        [<c1652cc5>] driver_probe_device+0x1c5/0x280
        [<c1498172>] ? pci_match_device+0xd2/0x100
        [<c1652e09>] __driver_attach+0x89/0x90
        [<c1652d80>] ? driver_probe_device+0x280/0x280
        [<c165114f>] bus_for_each_dev+0x4f/0x80
        [<c165269e>] driver_attach+0x1e/0x20
        [<c1652d80>] ? driver_probe_device+0x280/0x280
        [<c1652317>] bus_add_driver+0x1a7/0x220
        [<c1653a79>] driver_register+0x59/0xe0
        [<c1f897b8>] ? igb_init_module+0x49/0x49
        [<c1497b2a>] __pci_register_driver+0x4a/0x50
        [<c1f8985d>] ixgbe_init_module+0xa5/0xc4
        [<c1000485>] do_one_initcall+0x35/0x150
        [<c107e818>] ? parameq+0x18/0x70
        [<c1f395d8>] ? repair_env_string+0x12/0x51
        [<c107ead0>] ? parse_args+0x260/0x3b0
        [<c1074f73>] ? __usermodehelper_set_disable_depth+0x43/0x50
        [<c1f39e90>] kernel_init_freeable+0x19b/0x267
        [<c1f395c6>] ? set_debug_rodata+0xf/0xf
        [<c10b1e7b>] ? trace_hardirqs_on+0xb/0x10
        [<c1abdc02>] ? _raw_spin_unlock_irq+0x32/0x50
        [<c1085f0b>] ? finish_task_switch+0xab/0x1f0
        [<c1085ec9>] ? finish_task_switch+0x69/0x1f0
        [<c1ab6a30>] kernel_init+0x10/0x110
        [<c108bd65>] ? schedule_tail+0x25/0x80
        [<c1abe422>] ret_from_kernel_thread+0xe/0x24
        [<c1ab6a20>] ? rest_init+0x130/0x130

       This CallTrace occurred on 32-bit kernel with CONFIG_PROVE_LOCKING
       enabled.

       This happens at ixgbe driver probe hardware stage, when comes to
       ixgbe_get_stats64, the seqcount/seqlock still not initialize, although
       this was initialize in TX/RX resources setup routin, but it was too late,
       then lockdep give this Warning.

       To fix this, move the u64_stats_init function to driver probe stage,
       which before we get the status of seqcount and after the RX/TX ring
       was finished init.

       Signed-off-by: Liwei Song <liwei.song@windriver.com>
       Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>

   Author: Kexin(Casey) Chen <Casey.Chen@windriver.com>
   Date:   Tue Nov 29 14:14:07 2016 -0800

       aufs: fix compile warning

       fs/aufs/debug.h:95:19: warning: comparison of constant '0'
       with boolean expression is always false [-Wbool-compare]
          if (unlikely((e) < 0)) \
                           ^

       fs/aufs/vdir.c:852:2: note: in expansion of macro 'AuTraceErr'
          AuTraceErr(!valid);
          ^~~~~~~~~~

       In expansion of AuTraceErr(!valid), comparison of (!valid)
       and constant '0' always passes unlikely(x) false. function
       'static int seek_vdir(struct file *file, struct dir_context *ctx)'
       is to find whether there is a valid vd_deblk following ctx->pos.
       return 1 means valid, 0 for not. Change to AuTraceErr(valid - 1)
       makes more sense.

       Signed-off-by: Kexin(Casey) Chen <Casey.Chen@windriver.com>
       Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>

(From OE-Core rev: ae7d870954cf6a3608933335fedc425677aee0e3)

(From OE-Core rev: 815e3fdaa7964773587e24d40f3eaedc00cae10b)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Robert Yang
d33274cd75 diffutils: do_configure: fix "Argument list too long"
Fixed when len(TMPDIR) =  410:
aclocal: error: cannot open echo [snip]: Argument list too long

This is becuase it has a lot of m4 files, use relative path for them
can fix the problem.

It doesn't happen when MACHINE="qemux86", I think it is because
intel-x86-64 is longer than qemux86.

(From OE-Core rev: 5210ccd61ef52a191454a4587cfeb22079df746d)

(From OE-Core rev: 3903e93c50616b592ac1a2a241573305bb9265a9)

Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Andreas Oberritter
b3484ab7f6 kernel.bbclass: fix kernel_do_compile for KERNEL_IMAGETYPE = "vmlinux.gz" on mips
The target directory didn't exist.

(From OE-Core rev: bd62851dc236a0279c735b290782602e275de5c1)

(From OE-Core rev: a7c49e98cff402b5400643ae2a04ae3f345c5bce)

Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Andreas Oberritter
45c87f4b4b kernel.bbclass: do not copy bundled initramfs to /boot
These files cause warnings because they don't get packaged, now that they
don't land in kernel-vmlinux anymore.

(From OE-Core rev: a49569e3a7534779bbe3f01a0647fd076c95798d)

(From OE-Core rev: 6a4e09b295d760654fd43897841c014d50f109ab)

Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Andreas Oberritter
b6df490f47 kernel.bbclass: Avoid wildcards for kernel images
With multiple kernel images enabled starting with 'vmlinux', e.g.
vmlinux.gz and vmlinux.bin, all files landed inside the
kernel-vmlinux package.

On top of that, even initramfs images were included, e.g.
vmlinux.gz-initramfs-*.

(From OE-Core rev: b7f4133b44b740e8ac8e758b0d4a3ee32d326332)

(From OE-Core rev: a248ef51ae680e81cf78f07fe242ac6e01a5fcb4)

Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Andreas Oberritter
5b0b9943f5 kernel.bbclass: Use real filenames in kernel packages
When iterating over kernel image types to set up their packaging
variables, don't use make targets but the real names.

It was surprising if both vmlinux.bin and vmlinux.gz were enabled
and only the latter had its filename extension removed from the
package name.

(From OE-Core rev: aa189f183e10588f7e8d642f351bd9b8d69f3ea9)

(From OE-Core rev: 07e93839ee0dc25904fb93d6ae236e3ab16982ec)

Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Andreas Oberritter
2d74e26228 kernel.bbclass: allow uncompressed initramfs archives
The code failed to copy the initramfs in case it was a plain
cpio archive.

(From OE-Core rev: 7dbdb4ea91aa027866da2bd46c65fe65a25c848f)

(From OE-Core rev: 0d65292296ed9fb82e7bfbcca42d4b7a39ba6ca9)

Signed-off-by: Andreas Oberritter <obi@opendreambox.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Paul Eggleton
1dcc0ab902 recipetool: fix encoding-related errors creating python recipes
Yet another instance of us expecting a string back from subprocess when
in Python 3 what you get back is bytes. Just decode the output within
run_command() so we avoid this everywhere.

(From OE-Core rev: 103faae78cdff5280c7b7cdb7ca01e0868d02ec9)

(From OE-Core rev: f9e0267a64069fa2488ceb7ca1f6dbe5bfb66c18)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Alexander Kanavin
e8b00a62b1 grub2: enforce -no-pie if supported by compiler
Recent distros are enabling -pie by default; in case of grub
we need to turn it off.

(From OE-Core rev: aaff6c99dde3f1058bb3c4b320f27753c6c992ad)

(From OE-Core rev: ba7cfc296b07fe62d46a6c143d9a7d344de9f446)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Mingli Yu
4dd5ede472 tiff: Fix several CVE issues
Fix CVE-2016-9533, CVE-2016-9534, CVE-2016-9536 and
CVE-2016-9537

External References:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9533
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9534
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9536
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9537

Patch from:
83a4b92815 (diff-c8b4b355f9b5c06d585b23138e1c185f)

(From OE-Core rev: f75ecefee21ef89b147fff9afae01a6f09c93198)

(From OE-Core rev: 48d672e514d730ddda14f25f19f09c6d865a6526)

Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Mingli Yu
7760427c61 tiff: Security fix CVE-2016-9538
* tools/tiffcrop.c: fix read of undefined buffer in
readContigStripsIntoBuffer() due to uint16 overflow.

External References:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9538

Patch from:
43c0b81a81 (diff-c8b4b355f9b5c06d585b23138e1c185f)

(From OE-Core rev: 9af5d5ea882c853e4cb15006f990d3814eeea9ae)

(From OE-Core rev: 33cad1173f6d1b803b794a2ec57fe8a9ef19fb44)

Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Mingli Yu
5d2c218f57 tiff: Security fix CVE-2016-9535
* libtiff/tif_predict.h, libtiff/tif_predict.c:
Replace assertions by runtime checks to avoid assertions in debug mode,
or buffer overflows in release mode. Can happen when dealing with
unusual tile size like YCbCr with subsampling.

External References:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9535

Patch from:
3ca657a879
6a984bf790

(From OE-Core rev: 61d3feb9cad9f61f6551b43f4f19bfa33cadd275)

(From OE-Core rev: d55b4470c20f4a4b73b1e6f148a45d94649dfdb5)

Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Ross Burton
b6d7bc53e2 tiff: set CVE NAME
(From OE-Core rev: a28dc4cf7a8f67444f2f88248966478e385491d2)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Richard Purdie
3c6b603bc7 subversion: Fix issues in LDFLAGS sed manipulation
The existing sed expression can match expressions like
--sysroot=/some/path/xxx-linux/ which clearly isn't intended and
injects incorrect paths into LDFLAGS.

Fix this in the same way we address the problem in CFLAGS. This fixes corrupt
build paths and incorrect paths in .la files amongst other issues.

(From OE-Core rev: 9a8382422ddbb0972dc25b752204f4908bb9857c)

(From OE-Core rev: 980140fc0735df66592c09acda9686386711f2b5)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Richard Purdie
ef7ccf837b attr: Convert SSTATEPOSTINSTFUNCS to a do_install_append
A SSTATEPOSTINSTFUNCS function here is overkill, just do this in a
do_install_append_class-native and create relative symlinks rather
than absolute ones which would then have to be relocated.

(From OE-Core rev: 518e8d0216b0f42f574e42288804f553b9ff6f99)

(From OE-Core rev: f884ee9b911d1ce38b84d90113113c6e8c30253b)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Richard Purdie
56fb4af388 staging: Drop unused SYSROOT_LOCK
This hasn't been used in years and isn't referenced anywhere, drop
the definition.

(From OE-Core rev: 68258f856f08f35813964e58ef761471e29373ad)

(From OE-Core rev: b8b261d2e40457ee2e0cf1e8f40bd22230eb8ca7)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Bruce Ashfield
587b9ecd37 kernel-yocto: exit on non-zero return code
Historically the processing of kernel meta data contained some
commands that exited with a non-zero return code. Special processing
was required to properly deal with their exit.

That is no longer true, and instead of handling all return codes
and doing an explicit 'exit' call, we can remove set -e from the
routine and have all errors be trapped and stop processing.

(From OE-Core rev: 476ffd57cf5b6fba40d4e3f5dd913824ab8a8d3d)

(From OE-Core rev: 620c74336dad517037fcf26c8f7bf8c013b213c1)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:44 +00:00
Bruce Ashfield
443ce32b63 kern-tools: fix processing for no branch meta-data
Lernel meta-data that has patches, but no branches, can trigger an
error due to no branch specific patch queue.

This error then cascades to more issues since the tools are using
a named file in /tmp to store and display error messages to the
user.

We fix both issues though the following kern tools tweaks:

  commit bd9e1d6c9b0a34ff3e19a06999aaf57ffadfd04c
  Author: Bruce Ashfield <bruce.ashfield@windriver.com>
  Date:   Fri Dec 2 13:09:40 2016 -0500

    scc: use mktemp for consolidated output capture

    To provide useful error messages the tools dump pre-processed
    files and messages to a temporary file. If multiple users are
    doing builds, this means they either race, or can have permissions
    issues.

    By creating the temporary file via mktemp, we avoid both issues.
    (We also make sure to clean these up on exit, or /tmp will get
    polluted quickly).

  commit a287da4bfe0b4acb8f2b0627bd8e7abd1a1dde26
  Author: Bruce Ashfield <bruce.ashfield@windriver.com>
  Date:   Fri Dec 2 13:08:08 2016 -0500

    patch: do not assume a branch specific patch queue is needed

    When processing input files per-branch and global patch queues are
    generated. If the meta-data has not created any branches in the
    repo, no branch specific queue is required.

    The tools assumed that one is always valid, and hence would throw a
    non-zero exit code and stop processing.

    By testing for a named per-branch queue, we avoid this issue.

(From OE-Core rev: 0fd7da7375f0dcc59b56791fd482de557507c04c)

(From OE-Core rev: 6bc941a2a8e83e2db409af50ad77a0932e3ffe28)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Bruce Ashfield
9a36dcdb9b linux-yocto-dev: update to 4.9-rcX
(From OE-Core rev: 27c53cb8d0f1d408cb9791697305187944ad07b9)

(From OE-Core rev: c71f23e5ad72368045c44026955664dc69faef66)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Bruce Ashfield
1ca43bb304 linux-yocto/4.8: update to v4.8.10
Integrating the 4.8.9 and 4.8.10 -stable updates. The commit log is
as follows:

   cf5ae2989a32 Linux 4.8.10
   5cd8f6788ff3 usb: gadget: f_fs: stop sleeping in ffs_func_eps_disable
   e2458382c792 usb: gadget: f_fs: edit epfile->ep under lock
   e34a0f1c53b5 sparc64: Delete now unused user copy fixup functions.
   af97481a6f5b sparc64: Delete now unused user copy assembler helpers.
   ac663c54f40b sparc64: Convert U3copy_{from,to}_user to accurate exception reporting.
   d91bb7a87e26 sparc64: Convert NG2copy_{from,to}_user to accurate exception reporting.
   a15859f9d839 sparc64: Convert NGcopy_{from,to}_user to accurate exception reporting.
   bb522726d311 sparc64: Convert NG4copy_{from,to}_user to accurate exception reporting.
   b0580eadc19f sparc64: Convert U1copy_{from,to}_user to accurate exception reporting.
   50e927483ccf sparc64: Convert GENcopy_{from,to}_user to accurate exception reporting.
   620ec41010d1 sparc64: Convert copy_in_user to accurate exception reporting.
   bf4d0da8e800 sparc64: Prepare to move to more saner user copy exception handling.
   bbbab9f59ea7 sparc64: Delete __ret_efault.
   81a91edbb91a sparc64: Handle extremely large kernel TLB range flushes more gracefully.
   7f8a50eb38d3 sparc64: Fix illegal relative branches in hypervisor patched TLB cross-call code.
   f7ef55af2f1b sparc64: Fix instruction count in comment for __hypervisor_flush_tlb_pending.
   2a28ab3d4148 sparc64: Fix illegal relative branches in hypervisor patched TLB code.
   f4fb552a033e sparc64: Handle extremely large kernel TSB range flushes sanely.
   51915c6d9070 sparc: Handle negative offsets in arch_jump_label_transform
   da6fe239ceff spi: spidev_test: fix build with musl libc
   4ea98e573d65 net: stmmac: Fix lack of link transition for fixed PHYs
   150b491b1b88 sctp: change sk state only when it has assocs in sctp_shutdown
   5235fcfa6cf8 bnx2: Wait for in-flight DMA to complete at probe stage
   6523ff2e27fe Revert "bnx2: Reset device during driver initialization"
   224fb8cbefb2 mlxsw: spectrum_router: Correctly dump neighbour activity
   9092bbd64bd9 mlxsw: spectrum: Fix refcount bug on span entries
   5712922773b5 Revert "include/uapi/linux/atm_zatm.h: include linux/time.h"
   2b5f22e4f7fd tcp: take care of truncations done by sk_filter()
   22a78d4c7f43 ipv4: use new_gw for redirect neigh lookup
   bccb4093d464 net: __skb_flow_dissect() must cap its return value
   a1632e969a55 net: icmp_route_lookup should use rt dev to determine L3 domain
   9885f474d92b sock: fix sendmmsg for partial sendmsg
   b78ba0a0f231 fib_trie: Correct /proc/net/route off by one error
   92fd1c1f2fd2 net: icmp6_send should use dst dev to determine L3 domain
   09ee09498bca bpf: fix htab map destruction when extra reserve is in use
   de289ad2e575 sctp: assign assoc_id earlier in __sctp_connect
   76b5fee5cfa0 ipv6: dccp: add missing bind_conflict to dccp_ipv6_mapped
   84d9c612bb7a ipv6: dccp: fix out of bound access in dccp_v6_err()
   ba93cf7d2118 dccp: fix out of bound access in dccp_v4_err()
   378a61101374 dccp: do not send reset to already closed sockets
   72b03e549b95 dccp: do not release listeners too soon
   b3523a0773ed tcp: fix return value for partial writes
   1f49cc6fa91c ipv4: allow local fragmentation in ip_finish_output_gso()
   842a858fa048 tcp: fix potential memory corruption
   fc3b825f2c81 ip6_tunnel: Clear IP6CB in ip6tunnel_xmit()
   f5f4b71d5632 bgmac: stop clearing DMA receive control register right after it is set
   0c7f764d2c6a net: mangle zero checksum in skb_checksum_help()
   ac22a3ba0796 net: clear sk_err_soft in sk_clone_lock()
   5b078dc6fb64 dctcp: avoid bogus doubling of cwnd after loss
   876577321657 Linux 4.8.9
   07d00beb1e04 netfilter: fix namespace handling in nf_log_proc_dostring
   8ef009e09c13 drm/i915: Fix mismatched INIT power domain disabling during suspend
   88a45e5d2c0d drm/amdgpu: fix a vm_flush fence leak
   25ed6e4b0b65 drm/amdgpu: fix fence slab teardown
   de5e9aa77a3c NFSv4.1: work around -Wmaybe-uninitialized warning
   18c801047a18 libceph: fix legacy layout decode with pool 0
   53c1792b94da memcg: prevent memcg caches to be both OFF_SLAB & OBJFREELIST_SLAB
   02e1ee6b3e1c mmc: mxs: Initialize the spinlock prior to using it
   ce0702e35aeb pinctrl: iproc: Fix iProc and NSP GPIO support
   320244ac9eb6 ASoC: sun4i-codec: return error code instead of NULL when create_card fails
   2140d4fd9277 ASoC: Intel: Skylake: Always acquire runtime pm ref on unload
   5037fdbc62c2 gpio: of: fix GPIO drivers with multiple gpio_chip for a single node
   7a9239fd0480 gpio/mvebu: Use irq_domain_add_linear
   6de98e87effb batman-adv: Modify neigh_list only with rcu-list functions
   a3f000ce7b44 ACPI/PCI: pci_link: Include PIRQ_PENALTY_PCI_USING for ISA IRQs
   6c76dd0c7066 ACPI/PCI: pci_link: penalize SCI correctly
   86c711665c84 ACPI/PCI/IRQ: assign ISA IRQ directly during early boot stages
   ad185d9251e1 ACPI / APEI: Fix incorrect return value of ghes_proc()
   b55ebc89ab1d mmc: sdhci-msm: Fix error return code in sdhci_msm_probe()
   85284c0850f9 i40e: fix call of ndo_dflt_bridge_getlink()
   1242c9dfab0c hwrng: core - Don't use a stack buffer in add_early_randomness()
   c1a2ada73dac lib/genalloc.c: start search from start of chunk
   06bb5ebedbb4 s390/dumpstack: restore reliable indicator for call traces
   1ef1bd02ad23 rtc: pcf2123: Add missing error code assignment before test
   4baabb72e9dd clk: samsung: clk-exynos-audss: Fix module autoload
   3bbdbd8aa3c8 x86/build: Fix build with older GCC versions
   f5eadc27a60c Revert "clocksource/drivers/timer_sun5i: Replace code by clocksource_mmio_init"
   645a6b823739 nvme: Delete created IO queues on reset
   07c4cbe01341 svcrdma: Tail iovec leaves an orphaned DMA mapping
   4131e00a436e svcrdma: Skip put_page() when send_reply() fails
   755ab7aa1466 mei: bus: fix received data size check in NFC fixup
   d1b564536c6a perf top: Fix refreshing hierarchy entries on TUI
   6ac4e06b717f Input: synaptics-rmi4 - fix error handling in I2C transport driver
   d3716f1b3e4b Input: synaptics-rmi4 - fix error handling in SPI transport driver
   66503ec38f34 watchdog: core: Fix devres_alloc() allocation size
   c5e9e5cc8cd1 agp/intel: Flush chipset writes after updating a single PTE
   813617a4c8dc iommu/vt-d: Fix dead-locks in disable_dmar_iommu() path
   b6ef0b142208 iommu/amd: Free domain id when free a domain of struct dma_ops_domain
   2ef38255b588 iommu/io-pgtable-arm: Check for v7s-incapable systems
   d3d9428d7133 xprtrdma: Fix DMAR failure in frwr_op_map() after reconnect
   31c749bee3de xprtrdma: use complete() instead complete_all()
   67080e2785a3 drm/amd: fix scheduler fence teardown order v2
   b0da5ab2ffb5 drm/amdgpu: fix sched fence slab teardown
   920a85ba4306 tty/serial: at91: fix hardware handshake on Atmel platforms
   9d76a886eb2f drm/amdgpu: fix crash in acp_hw_fini
   6e652d18d73d drm/amdgpu: disable runtime pm in certain cases
   8c8fdc683295 drm/i915/dp: Extend BDW DP audio workaround to GEN9 platforms
   db8e005bf2ba drm/i915/dp: BDW cdclk fix for DP audio
   f50b7450a8e4 drm/i915: Respect alternate_ddc_pin for all DDI ports
   e1b24f6a0b3c drm/radeon: disable runtime pm in certain cases
   eb13abb0e515 KVM: arm/arm64: vgic: Prevent access to invalid SPIs
   2850fad5acb0 scsi: scsi_dh_alua: Fix a reference counting bug
   5fac70d772a4 scsi: scsi_dh_alua: fix missing kref_put() in alua_rtpg_work()
   f29bcd11a170 scsi: mpt3sas: Fix for block device of raid exists even after deleting raid disk
   b2040deabb07 scsi: qla2xxx: Fix scsi scan hang triggered if adapter fails during init
   1281b9683f96 iio: st_sensors: fix scale configuration for h3lis331dl
   4dfb6d1dd11d iio: orientation: hid-sensor-rotation: Add PM function (fix non working driver)
   341c5534edad iio: hid-sensors: Increase the precision of scale to fix wrong reading interpretation.
   b9d031f354da cdc-acm: fix uninitialized variable
   c480880cd12c clk: qoriq: Don't allow CPU clocks higher than starting value
   ee27fd32c499 toshiba-wmi: Fix loading the driver on non Toshiba laptops
   f713523a234c drbd: Fix kernel_sendmsg() usage - potential NULL deref
   31da266e4b9a usb: gadget: u_ether: remove interrupt throttling
   264e4131a167 USB: cdc-acm: fix TIOCMIWAIT
   c12c24eeaf77 usb: dwc3: Fix error handling for core init
   6b95417150b7 staging: nvec: remove managed resource from PS2 driver
   82239ab105a5 Revert "staging: nvec: ps2: change serio type to passthrough"
   529789866abe drivers: staging: nvec: remove bogus reset command for PS/2 interface
   dea774aac054 staging: comedi: ni_tio: fix buggy ni_tio_clock_period_ps() return value
   5d510185f99a staging: sm750fb: Fix bugs introduced by early commits
   45983d678b70 staging: iio: ad5933: avoid uninitialized variable in error case
   5289e59246dd mmc: mmc: Use 500ms as the default generic CMD6 timeout
   ce4dfe7d927e mmc: sdhci: Fix unexpected data interrupt handling
   bde8d3f73375 mmc: sdhci: Fix CMD line reset interfering with ongoing data transfer
   10d24701f3f4 cpupower: Correct return type of cpu_power_is_cpu_online() in cpufreq-set
   f062e738c19b pinctrl: cherryview: Prevent possible interrupt storm on resume
   1d99fe3317e3 pinctrl: cherryview: Serialize register access in suspend/resume
   f5ad96462615 arc: Implement arch-specific dma_map_ops.mmap
   004e7c97f181 PCI: Don't attempt to claim shadow copies of ROM
   7fac0361f94e ARC: timer: rtc: implement read loop in "C" vs. inline asm
   4058116db4d0 s390/hypfs: Use get_free_page() instead of kmalloc to ensure page alignment
   2f3e0b82ebe9 coredump: fix unfreezable coredumping task
   d6ee4f47e2e7 mm/hugetlb: fix huge page reservation leak in private mapping error paths
   e87bf4f558f1 mm: hwpoison: fix thp split handling in memory_failure()
   67c79e166d46 swapfile: fix memory corruption via malformed swapfile
   c87739e5d029 shmem: fix pageflags after swapping DMA32 object
   5b5243b606ec mm, frontswap: make sure allocated frontswap map is assigned
   2e594273d4c5 dib0700: fix nec repeat handling
   9964230320d5 ASoC: cs4270: fix DAPM stream name mismatch
   9386a722d250 ALSA: info: Limit the proc text input size
   c3ea1b15b71e ALSA: info: Return error for invalid read/write

(From OE-Core rev: b5e43be6aaf912cf6c679ee98ed61cf34dd00ee8)

(From OE-Core rev: 05c1981319f4f5637e72ed4f86e91d38483c8dc8)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Jair Gonzalez
bbc7130507 parselogs: Whitelist GPT warnings as the device is fully functional
The warning occurs when the GPT image is not the same size than the
media into which it's being flashed, causing the backup GPT table
not being at the end of the disk. However, this is expected as the
image is created before having the information about the destination
media. The error is harmless, so it will be whitelisted.

Fixes [YOCTO 10481].

(From OE-Core rev: 5cc5cdc788308a79f8f0706e6d794c602ef427ed)

(From OE-Core rev: 941194d29d8e4c334d3f85ce7709c894cf34b8d1)

Signed-off-by: Jair Gonzalez <jair.de.jesus.gonzalez.plascencia@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
California Sullivan
745517685b parselogs.py: Whitelist iwlwifi firmware load error messages
The iwlwifi module of any given kernel has a minimum and maximum
supported firmware version. The kernel begins by attempting to load the
maximum version, and decrements until it is successful. The 4.8 kernel's
maximum supported firmware version is 24, but thus far only 22 has been
released, meaning we get errors for 24 and 23.

Filter out iwlwifi firmware load error messages, as they are not
necessarily indicative of real problems.

(From OE-Core rev: 7df570c2310efac8f9898da15deaac2b7df16655)

(From OE-Core rev: 23aa95a8a15cd0b7bdc43dba9375e139f4b20607)

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Patrick Ohly
ed9e0b8aaf scripts/send-pull-request: Avoid multiple chain headers
When creating a patch set with cover letter using the
send-pull-request script, both the "In-Reply-To" and "References"
headers are appended twice in patch 2 and subsequent.

That's because git-format-patch already inserted them and then
git-send-email repeats that. Suppressing mail threading in
git-send-email with --no-thread avoids the problem and is the
right solution because it works regardless whether git-send-email is
called once or twicee.

Repeating these headers is a violation of RFC 2822 and can confuse
mail programs. For example, Patchwork does not detect a patch series
problem when there are these extra headers.

[YOCTO #10718]

(From OE-Core rev: 303a1aa3df43eb0b693d8602062fa33c4a08fdd6)

(From OE-Core rev: 025d21b856e650c8edefd2d06493e84f8416d50f)

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Martin Vuille
926f3dfe2d terminal.py: Pass string instead of bytes to ExecutionError to avoid exception
Based on run() in bitbake/lib/bb/process.py, ExecutionError() expects strings
not bytes. Passing bytes results in a "TypeError: Can't convert 'bytes' object
to str implicitly" exception.

Fixes Bug 10729

(From OE-Core rev: 063b63d4d324c23322ac1b6b7c7928e725d7b968)

(From OE-Core rev: df4d5246d47acc54aa322b777364c9b86f9a4c54)

Signed-off-by: Martin Vuille <jpmv27@yahoo.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Yi Zhao
4073438491 libxml2: Security fix CVE-2016-5131
CVE-2016-5131 libxml2: Use-after-free vulnerability in libxml2 through
2.9.4, as used in Google Chrome before 52.0.2743.82, allows remote
attackers to cause a denial of service or possibly have unspecified
other impact via vectors related to the XPointer range-to function.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-5131

Patch from:
https://git.gnome.org/browse/libxml2/commit/?id=9ab01a277d71f54d3143c2cf333c5c2e9aaedd9e

(From OE-Core rev: 640bd2b98ff33e49b42f1087650ebe20d92259a4)

(From OE-Core rev: 1e284447b9bf42e1fd6080f5a50fe01c8267a4e6)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Zhixiong Chi
6fe39199a4 tiff: Security fix CVE-2016-9539
tools/tiffcrop.c in libtiff 4.0.6 has an out-of-bounds read in
readContigTilesIntoBuffer(). Reported as MSVR 35092.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9539

Patch from:
ae9365db1b

(From OE-Core rev: 58bf0a237ca28459eb8c3afa030c0054f5bc1f16)

(From OE-Core rev: 0933a11707a369c8eaefebd31e8eea634084d66e)

Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Zhixiong Chi
3f0c6a8f5c tiff: Security fix CVE-2016-9540
tools/tiffcp.c in libtiff 4.0.6 has an out-of-bounds write on tiled
images with odd tile width versus image width. Reported as MSVR 35103,
aka "cpStripToTile heap-buffer-overflow."

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9540

Patch from:
5ad9d8016f

(From OE-Core rev: cc97dc66006c7892473e3b4790d05e12445bb927)

(From OE-Core rev: ad2c4710ef15c35f6dd4e7642efbceb2cbf81736)

Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
David Vincent
2fa2739850 slang: Disable parallel make install
Installation task fails if run in parallel. This case happens if we
define PARALLEL_MAKEINST to a different value of PARALLEL_MAKE.

(From OE-Core rev: bbe59d7c49b540d65c871666c95cc89a23cab474)

(From OE-Core rev: 1aff7c867c0ad926f204459b65d3088900871ec9)

Signed-off-by: David Vincent <freesilicon@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Mark Asselstine
d87772571f systemd.bbclass: don't block on service restart
The current class works fine when a recipe uses SYSTEMD_AUTO_ENABLE
'enable' and has no on device pkg_postinst(), ie when the postinst is
run as part of rootfs creation.  However, when there is a component of
pkg_postinst() that is run on device the 'systemctl restart' is run as
part of the run_postinsts.service at boot. This results in the boot
spinning indefinitely with:

[ *** ] A start job is running for Run pending postinsts (7s / no limit)

The issue could potentially be that the packages service has an
'After' clause which comes later in the boot, beyond
run_postinsts.service, creating a chicken before the egg
scenario. Even service files without an 'After' clause cause this
situation however. Despite this not being the cause of the issue this
fix will prevent this scenario from happenning.

Using strace we are able to find that during boot, when
run_postinsts.service is running attempting to start or restart any
service will result in the call get stuck on poll(). Since the
run_postinsts.service does not monitor the outcome of the call to
restart we can work around this by using '--no-block'.

(From OE-Core rev: 6ad6a0084a73088fc2a27ab9958e5c46d6e094fc)

(From OE-Core rev: caad8aa89f9815a278e39296497596996a35fe95)

Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Aníbal Limón
cebbc4372a perl: Fix ptest update hash of ExtUtils/Liblist/Kid.pm in customized.dat
The perl ptest is failing due to a patch changes the file
ExtUtils/Liblist/Kid.pm and the customized.dat file wasn't updated.

[YOCTO #8656]

(From OE-Core rev: 0ed3cc09e3988367fa57bd08fb7db12b7fb9dabe)

(From OE-Core rev: 5a0ee17cf17ce0b0deac54f990e2128674768b38)

Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Ed Bartosh
14f514d93c qemux86*.conf: set wic-related parameters
Set directdisk.wks as default wks to use for qemux86 machines.
Set requried dependeincies to build directdisk image.

This should simplify building wic images for qemux86* machines.
It should be enough to add wic to the list of IMAGE_FSTYPES to get
the images built.

[YOCTO #10637, YOCTO #8719]

(From OE-Core rev: 8716b8b9be05e3f140bfa426a8e0d4eeaa2edcbe)

(From OE-Core rev: 3d99674a712cf06c62aa3a98b6696d430547fcec)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Patrick Ohly
793092d1a1 pseudo: include fix for xattr corruption
pseudo_1.8.1.bb gets the backported patch and pseudo_git.bb gets
updated to include the commit.

(From OE-Core rev: 4e98f3a6e6f61d9d9037ac828b9c4869f7e11458)

(From OE-Core rev: 264114805cc942e052e79bdaa5ae7978d68fdd8e)

Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Samuli Piippo
903c4158a5 mesa: make sure GLES3 headers are installed
Since there is no libgles3-mesa package that would pull in the headers,
add dependency to libgles2-mesa-dev. Now there no need to manually add
GLES3 headers to image or toolchain.

(From OE-Core rev: a93bbfa096cd7de8e935c6c2d2ad98d72a1c297f)

(From OE-Core rev: fd02a12e875a900e46f50d92772098298ed4bc73)

Signed-off-by: Samuli Piippo <samuli.piippo@qt.io>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Ross Burton
468b78967a insane: rewrite the expanded-d test as a QAPKGTEST
Instead of being executed for every file in every package, this is now just
called for each package.  It is also now correctly called for packages which
don't have any content but do have postinst scripts.

[ YOCTO #10711 ]

(From OE-Core rev: afda72b2424528eaff9054327530bdf5654bec66)

(From OE-Core rev: b653bfb800a470894ec93c8bb4acd12a143716a6)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Ross Burton
93b13d9995 insane: add QAPKGTEST, a package-wide equivilant to QAPATHTEST
QAPATHTEST defines a function that is executed for every file in every package.
For tests which just need to look at the datastore this is massive overkill.

Add QAPKGTEST, which is invoked for each package in the recipe.

(From OE-Core rev: acc3cc26099c77e4eeb44c75bc7167ab58ef1147)

(From OE-Core rev: e7751fa0bdb5bc9b217a0bf267a9c658bec997fa)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Ross Burton
67965302e2 insane: factor out the test matrix processing
Pull the test matrix processing out as a function so it can be reused.

(From OE-Core rev: 3caccd3f6079b7e284d32e1eb0217107425e7bf8)

(From OE-Core rev: 3b21c285d4ff08ae6f613700c5936e39e7e3051d)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:43 +00:00
Ross Burton
71c8568b38 insane: fix expanded-d test
This test should be looking for the expanded value of ${D} in the expanded value
of pkg_postinst and so on, but one of the getVar() calls was passing
expand=False so the test would never be true.

(From OE-Core rev: cc545044cba51317bee32e3bf674723e422e3a8a)

(From OE-Core rev: 9d4f094a7c9cbff0d3db5f339d084b2b7c70df86)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Alexandre Belloni
3a96984d3a insane: Add aarch64 baremetal mappings to the QA arch test
Add mappings for aarch64-elf and aarch64_be-elf to binary lookup table
which allows for the generation of baremetal toolchains.

(From OE-Core rev: e90a1c4b8fd7baa738eb4683e5eac60905e04296)

(From OE-Core rev: 9a8a4fe56901f88f143e86652edc7039345d49fc)

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Khem Raj
44a13f115d arch-arm64.inc: Include arch-armv7ve.inc
All armv8 implementations from a53 - a73 supports
virtual extentions

(From OE-Core rev: f896375c60d8ce0f1293f5329163172e946f46df)

(From OE-Core rev: 4bf27daace6528b1fa6062be0600ca36441d81f9)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
eee2e545d0 kern-tools: error checking and tree generation fixes
During processing of the kernel meta data the kern tools were
not properly exiting on syntax errors or invalid commands.

Noticing and debugging these issues wasn't trivial. To make this
easier, we now trap the error and dump the offending meta-data
for the user to see.

There was also an issue with creating branches during tree
generation, which is resolved by always switching to the
active branch.

The following are the commit logs of the changes themselves:

[
  commit b36f6f9a5695f2084b83823393e13ca42284bed9
  Author: Paul Gortmaker <paul.gortmaker@windriver.com>
  Date:   Sat Oct 22 17:23:25 2016 -0400

      kgit-scc: dont mention meta-repo in help ; it doesnt exist

      Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
      Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>

  commit 08463d684c1952e74c25344cddace4c3f24c739d
  Author: Bruce Ashfield <bruce.ashfield@windriver.com>
  Date:   Mon Oct 31 14:30:12 2016 -0400

      scc: exit on error

      If there is an error in the processing of the input files, scc
      should exit and inform the user.

      scc is executed on a combined/preprocessed file and as a result
      it doesn't have the granularity to see each input file individually.

      Rather than moving preprocessing into scc (from spp), we can trap
      the line number of the error and dump context around the line.
      This gives the user a pointer to the input file and the specific
      line that caused the problem.

      Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>

  commit bf99953e8ac14cee653e559f2d4a6022c847a182
  Author: Bruce Ashfield <bruce.ashfield@windriver.com>
  Date:   Fri Oct 28 21:23:27 2016 -0400

      kgit-meta: always checkout branches on branch commands

      During a tree generation we must always make the branch active when
      we see any kind of branch command. This ensures that any subsequent
      patches are applied in the proper context.

      Previously, only branch creation was changing the active branch, and
      this mean that tree generation was not determinstic and relied
      on the order of processing to generate a correct tree.

      Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
]

(From OE-Core rev: 83d10e2acef936b1f38804988f10eafa48db36f9)

(From OE-Core rev: 95dd034a5d911c6f703856d7baeb6e61cb625396)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
35207b387f linux-yocto/4.4: update to v4.4.32
Updating from v4.4.30 -> v4.4.32. The shortlog summary of the changes
follows:

   4dab3e4df994 Linux 4.4.32
   ae94da4c53b7 scsi: megaraid_sas: fix macro MEGASAS_IS_LOGICAL to avoid regression
   2be0548e64f1 drm/radeon: fix DP mode validation
   ccc31f819918 drm/radeon/dp: add back special handling for NUTMEG
   227994b52c73 drm/amdgpu: fix DP mode validation
   2e8cfc1fe985 drm/amdgpu/dp: add back special handling for NUTMEG
   72c13445dfb4 KVM: MIPS: Drop other CPU ASIDs on guest MMU changes
   c57deabd2b17 Revert KVM: MIPS: Drop other CPU ASIDs on guest MMU changes
   e28a472742bf of: silence warnings due to max() usage
   d21daf7f3ee8 packet: on direct_xmit, limit tso and csum to supported devices
   bd891f40f04f sctp: validate chunk len before actually using it
   7c230d0e546a net sched filters: fix notification of filter delete with proper handle
   d46c76765da6 udp: fix IP_CHECKSUM handling
   80d59090d4e3 net: sctp, forbid negative length
   1a680e543f84 ipv4: use the right lock for ping_group_range
   827ada2d671b ipv4: disable BH in set_ping_group_range()
   3cb00b90e8b1 net: add recursion limit to GRO
   02558fa0e061 rtnetlink: Add rtnexthop offload flag to compare mask
   ebfbfc2e4df8 bridge: multicast: restore perm router ports on multicast enable
   f467184e2323 net: pktgen: remove rcu locking in pktgen_change_name()
   e635b4766174 ipv6: correctly add local routes when lo goes up
   f9d4850af3c8 ip6_tunnel: fix ip6_tnl_lookup
   705b5aca17c3 ipv6: tcp: restore IP6CB for pktoptions skbs
   6d123f1d396b netlink: do not enter direct reclaim from netlink_dump()
   d72cb5fb36bd packet: call fanout_release, while UNREGISTERING a netdev
   63091b2c1dea net: Add netdev all_adj_list refcnt propagation to fix panic
   9edbf4a0b60b net/sched: act_vlan: Push skb->data to mac_header prior calling skb_vlan_*() functions
   bb7ffb6b68a9 net: pktgen: fix pkt_size
   bc5d8ced3c98 net: fec: set mac address unconditionally
   0ee4acb7b3be tg3: Avoid NULL pointer dereference in tg3_io_error_detected()
   6eb0061fa630 ipmr, ip6mr: fix scheduling while atomic and a deadlock with ipmr_get_route
   4f312a802994 ip6_gre: fix flowi6_proto value in ip6gre_xmit_other()
   aadcd6a96010 tcp: fix a compile error in DBGUNDO()
   ac40148543c5 tcp: fix wrong checksum calculation on MTU probing
   d2e01b15657c net: avoid sk_forward_alloc overflows
   a35ce624a3ae tcp: fix overflow in __tcp_retransmit_skb()
   beb996c1c399 Linux 4.4.31
   78bd7c9bf60b HID: usbhid: add ATEN CS962 to list of quirky devices
   69e14ce88389 ubi: fastmap: Fix add_vol() return value test in ubi_attach_fastmap()
   91e1f7b0eb25 kvm: x86: Check memopp before dereference (CVE-2016-8630)
   62fa839b8fff tty: vt, fix bogus division in csi_J
   93fe5c7bb4e0 usb: dwc3: Fix size used in dma_free_coherent()
   4b06152a4822 pwm: Unexport children before chip removal
   353bbacfd57f UBI: fastmap: scrub PEB when bitflips are detected in a free PEB EC header
   1d79b67c4a8a Disable "frame-address" warning
   c5b2cd97b1d3 smc91x: avoid self-comparison warning
   603c78000f8c cgroup: avoid false positive gcc-6 warning
   8a618bc7e586 drm/exynos: fix error handling in exynos_drm_subdrv_open
   26a5f0596ff2 mm/cma: silence warnings due to max() usage
   58fca2f1563b ARM: 8584/1: floppy: avoid gcc-6 warning
   f0b13816ad4f powerpc/ptrace: Fix out of bounds array access warning
   eeae15feceaf x86/xen: fix upper bound of pmd loop in xen_cleanhighmap()
   95f2bdbe50d0 perf build: Fix traceevent plugins build race
   9702108e3def drm/dp/mst: Check peer device type before attempting EDID read
   1262212d3b8e drm/radeon: drop register readback in cayman_cp_int_cntl_setup
   1734d4e14221 drm/radeon/si_dpm: workaround for SI kickers
   231be2b99e4a drm/radeon/si_dpm: Limit clocks on HD86xx part
   4b32256b2706 Revert "drm/radeon: fix DP link training issue with second 4K monitor"
   a1ffa7c37a4c mmc: dw_mmc-pltfm: fix the potential NULL pointer dereference
   c77a2346226e scsi: arcmsr: Send SYNCHRONIZE_CACHE command to firmware
   69ee0ed0c6f9 scsi: scsi_debug: Fix memory leak if LBP enabled and module is unloaded
   9075faf1406c scsi: megaraid_sas: Fix data integrity failure for JBOD (passthrough) devices
   d9237e75fd74 mac80211: discard multicast and 4-addr A-MSDUs
   1d22568ce5ed firewire: net: fix fragmented datagram_size off-by-one
   46e14262a063 firewire: net: guard against rx buffer overflows
   304cc8b5b437 Input: i8042 - add XMG C504 to keyboard reset table
   daac9e1c85c9 dm mirror: fix read error on recovery after default leg failure
   88586a4f884c virtio: console: Unlock vqs while freeing buffers
   50e1c4d90aff virtio_ring: Make interrupt suppression spec compliant
   f2d9107bd0a0 parisc: Ensure consistent state when switching to kernel stack at syscall entry
   e3d312c435dd ovl: fsync after copy-up
   ab69d3a03e22 KVM: MIPS: Make ERET handle ERL before EXL
   159766dff4d4 KVM: x86: fix wbinvd_dirty_mask use-after-free
   cb270a3f1666 dm: free io_barrier after blk_cleanup_queue call
   f49f9df84eb2 USB: serial: cp210x: fix tiocmget error handling
   00877d139396 tty: limit terminal size to 4M chars
   e8a806797070 xhci: add restart quirk for Intel Wildcatpoint PCH
   fde4a5f237ab hv: do not lose pending heartbeat vmbus packets
   3425e397fb23 vt: clear selection before resizing
   dc1555e670c3 Fix potential infoleak in older kernels
   bd5cc3294de3 GenWQE: Fix bad page access during abort of resource allocation
   ce423aca0126 usb: increase ohci watchdog delay to 275 msec
   54af73d02eb4 xhci: use default USB_RESUME_TIMEOUT when resuming ports.
   a98f0e91b0fc USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7
   f2ecc94504f4 USB: serial: fix potential NULL-dereference at probe
   660c04e8f174 usb: gadget: function: u_ether: don't starve tx request queue
   c0510383011f mei: txe: don't clean an unprocessed interrupt cause.
   dc70a200aac2 ubifs: Fix regression in ubifs_readdir()
   0222377bb2cb ubifs: Abort readdir upon error
   f0d6ba518421 btrfs: fix races on root_log_ctx lists
   8910c3388253 ANDROID: binder: Clear binder and cookie when setting handle in flat binder struct
   14f09e8e7cd8 ANDROID: binder: Add strong ref checks
   c5be1e1314ee ALSA: hda - Fix headset mic detection problem for two Dell laptops
   34a8b859da9f ALSA: hda - Adding a new group of pin cfg into ALC295 pin quirk table
   4a30dbab6584 ALSA: hda - allow 40 bit DMA mask for NVidia devices
   b0b3d37edb19 ALSA: hda - Raise AZX_DCAPS_RIRB_DELAY handling into top drivers
   aa72457de77b ALSA: hda - Merge RIRB_PRE_DELAY into CTX_WORKAROUND caps
   d08ae42a106d ALSA: usb-audio: Add quirk for Syntek STK1160
   940d7ecbc57c KEYS: Fix short sprintf buffer in /proc/keys show function
   299991298b04 mm: memcontrol: do not recurse in direct reclaim
   9fa32e04f810 mm/list_lru.c: avoid error-path NULL pointer deref
   fd9e4cea96df libxfs: clean up _calc_dquots_per_chunk
   0daca12d6774 h8300: fix syscall restarting
   44084f15b706 drm/dp/mst: Clear port->pdt when tearing down the i2c adapter
   4125fe7f8d31 i2c: core: fix NULL pointer dereference under race condition
   eeb1846df1c8 i2c: xgene: Avoid dma_buffer overrun

(From OE-Core rev: cdc73ef471c9bf304810a7457c0cb10116d70ef1)

(From OE-Core rev: 9620bb22013223d1cd24cd177e54206d4950cc41)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
a871504b70 linux-yocto/4.8: update from v4.8.6 -> v4.8.8
Updating to the korg -stable release 4.8.8. The short log change
summary follows:

   61385cc1db42 Linux 4.8.8
   8ed841d6c045 scsi: megaraid_sas: fix macro MEGASAS_IS_LOGICAL to avoid regression
   32f60e9b621f scsi: megaraid_sas: Fix data integrity failure for JBOD (passthrough) devices
   eb2ca7aac349 usb: dwc3: gadget: properly account queued requests
   38db26fb3ae5 arch/powerpc: Update parameters for csum_tcpudp_magic & csum_tcpudp_nofold
   a143c6022cef packet: on direct_xmit, limit tso and csum to supported devices
   a6289d9ac3fe ip6_tunnel: Update skb->protocol to ETH_P_IPV6 in ip6_tnl_xmit()
   c9e086b9009a sctp: validate chunk len before actually using it
   5a37dce1b679 net sched filters: fix notification of filter delete with proper handle
   d46b19687fec net: ipv6: Do not consider link state for nexthop validation
   eb77db88ea11 macsec: Fix header length if SCI is added if explicitly disabled
   027ab3b8ee5a netvsc: fix incorrect receive checksum offloading
   b75edf27a6c3 udp: fix IP_CHECKSUM handling
   5ee356021c42 sctp: fix the panic caused by route update
   d90cbfaf5439 net: sctp, forbid negative length
   64774617da37 net: fec: Call swap_buffer() prior to IP header alignment
   c6c82c2b707e ipv4: use the right lock for ping_group_range
   8418193f7052 ipv4: disable BH in set_ping_group_range()
   23c110c4cdbc net: add recursion limit to GRO
   d3bbd04b92fd net: core: Correctly iterate over lower adjacency list
   fc5722f8f8f2 rtnetlink: Add rtnexthop offload flag to compare mask
   4ac3ca8c2933 switchdev: Execute bridge ndos only for bridge ports
   63d82a2cbd0c bridge: multicast: restore perm router ports on multicast enable
   e9a5921c393f net: pktgen: remove rcu locking in pktgen_change_name()
   2eeb5735dd04 net/mlx4_en: fixup xdp tx irq to match rx
   27bb6e31d32d IB/ipoib: move back IB LL address into the hard header
   f280126ec8d8 ipv6: correctly add local routes when lo goes up
   0f3e77623916 ip6_tunnel: fix ip6_tnl_lookup
   a148a818df84 net: phy: Trigger state machine on state change and not polling.
   2a9099899a6a ipv6: tcp: restore IP6CB for pktoptions skbs
   50b43ad1dce6 net_sched: reorder pernet ops and act ops registrations
   dac04913ee27 drivers/ptp: Fix kernel memory disclosure
   3f841d1555ad netlink: do not enter direct reclaim from netlink_dump()
   5086cadf8fa4 packet: call fanout_release, while UNREGISTERING a netdev
   6fff1319fdac net: Add netdev all_adj_list refcnt propagation to fix panic
   9caee42c800e net/sched: act_vlan: Push skb->data to mac_header prior calling skb_vlan_*() functions
   c002dfd8adaa net: pktgen: fix pkt_size
   ff1b27c31706 net: fec: set mac address unconditionally
   567aeca9fbb7 Linux 4.8.7
   1bf121d3b234 HID: usbhid: add ATEN CS962 to list of quirky devices
   05a833d4b051 cpufreq: intel_pstate: Set P-state upfront in performance mode
   c89771511deb ubi: fastmap: Fix add_vol() return value test in ubi_attach_fastmap()
   591bf1362e9e btrfs: qgroup: Prevent qgroup->reserved from going subzero
   0c879624701d kvm: x86: Check memopp before dereference (CVE-2016-8630)
   725a92be3926 ARM: fix oops when using older ARMv4T CPUs
   e339609bf377 tty: vt, fix bogus division in csi_J
   4a22930a74ac v4l: vsp1: Prevent pipelines from running when not streaming
   59f9693a170a usb: musb: Fix hardirq-safe hardirq-unsafe lock order error
   086ac9180437 usb: chipidea: host: fix NULL ptr dereference during shutdown
   07bae478e1c1 usb: dwc3: Fix size used in dma_free_coherent()
   fedede0963c4 pwm: Unexport children before chip removal
   7b4b77b9566d omapfb: fix return value check in dsi_bind()
   a3e55d6342b2 video: fbdev: pxafb: potential NULL dereference on error
   13d0f5b3a399 uapi: add missing install of sync_file.h
   db5025bd08ef UBI: fastmap: scrub PEB when bitflips are detected in a free PEB EC header
   cc94524e8940 netfilter: xt_NFLOG: fix unexpected truncated packet
   720a40113e78 i2c: mark device nodes only in case of successful instantiation
   f7d8d44a68de drm: i915: Wait for fences on new fb, not old
   1cefe4cb4f8c drm/i915/fbc: fix CFB size calculation for gen8+
   809e9e6fc390 drm/i915: Clean up DDI DDC/AUX CH sanitation
   ba0a959e0334 drm/i915: Respect alternate_aux_channel for all DDI ports
   426a724c9972 drm: Release reference from blob lookup after replacing property
   5064a6a05387 drm/dp/mst: Check peer device type before attempting EDID read
   e6fcf953a995 drm/i915/gen9: fix watermarks when using the pipe scaler
   0f7f9c456380 drm/i915/gen9: fix DDB partitioning for multi-screen cases
   0cc98b5963f8 drm/fb-helper: Keep references for the current set of used connectors
   14f4a463dc78 drm/fb-helper: Fix connector ref leak on error
   6222f1e0b9ef drm/fb-helper: Don't call dirty callback for untouched clips
   7290da41b8da drm/nouveau/acpi: fix check for power resources support
   fd5f9e1e28cb drm/radeon: drop register readback in cayman_cp_int_cntl_setup
   e136de5d7331 drm/radeon/si_dpm: workaround for SI kickers
   fe777e7a595c drm/radeon/si_dpm: Limit clocks on HD86xx part
   fa6227dbfd6a drm/imx: ipuv3-plane: Access old u/vbo properly in ->atomic_check for YU12/YV12
   d040374f3473 drm/imx: ipuv3-plane: Switch EBA buffer only when we don't need modeset
   51ed5a2bbf38 Revert "drm/radeon: fix DP link training issue with second 4K monitor"
   ac6f210dd7a6 md: be careful not lot leak internal curr_resync value into metadata. -- (all)
   eba4fe9db92f RAID10: ignore discard error
   21faa6dbf53f RAID1: ignore discard error
   b80fcd58e6f6 mmc: dw_mmc-pltfm: fix the potential NULL pointer dereference
   1244d3c3a0f6 scsi: arcmsr: Send SYNCHRONIZE_CACHE command to firmware
   2a1a0a6f1d60 scsi: scsi_debug: Fix memory leak if LBP enabled and module is unloaded
   5bac49422b4a ath10k: cache calibration data when the core is stopped
   a7d092e946f5 Revert "ath9k_hw: implement temperature compensation support for AR9003+"
   aea7cb3b7ceb mac80211: discard multicast and 4-addr A-MSDUs
   27fa1e735c70 firewire: net: fix fragmented datagram_size off-by-one
   032430fb6a2c firewire: net: guard against rx buffer overflows
   facb17b67ac9 Input: i8042 - add XMG C504 to keyboard reset table
   8b535f07898a rtl8xxxu: Fix rtl8723bu driver reload issue
   1c9edb27261e rtl8xxxu: Fix big-endian problem reporting mactime
   ece1b51ae1c4 rtl8xxxu: Fix memory leak in handling rxdesc16 packets
   5a805cd29284 dm raid: fix activation of existing raid4/10 devices
   6e5456768ba1 dm raid: fix compat_features validation
   056290446e8a dm rq: clear kworker_task if kthread_run() returned an error
   13a59a868756 dm table: fix missing dm_put_target_type() in dm_table_add_target()
   159a17e8dbf6 dm mirror: fix read error on recovery after default leg failure
   d8db5234adef virtio: console: Unlock vqs while freeing buffers
   7569d22a820d virtio_pci: Limit DMA mask to 44 bits for legacy virtio devices
   0c2f67a6196d virtio_ring: Make interrupt suppression spec compliant
   c528df925fba parisc: Ensure consistent state when switching to kernel stack at syscall entry
   592de1000694 ovl: fsync after copy-up
   3ad464dadb7c ovl: update S_ISGID when setting posix ACLs
   be9015460ed5 ovl: fix get_acl() on tmpfs
   2b632307635f MIPS: KASLR: Fix handling of NULL FDT
   1734afcce32b nfsd: Fix general protection fault in release_lock_stateid()
   202c6676b963 ARM: dts: fix the SD card on the Snowball
   db20b510ca5c ARM: mvebu: Select corediv clk for all mvebu v7 SoC
   c627b2e76ae2 KVM: MIPS: Precalculate MMIO load resume PC
   f3a0c969e788 KVM: MIPS: Make ERET handle ERL before EXL
   961cf133b710 KVM: s390: Fix STHYI buffer alignment for diag224
   88aca01f8cb4 KVM: x86: fix wbinvd_dirty_mask use-after-free
   ea261d177aed dm: free io_barrier after blk_cleanup_queue call
   377a2a273c4b Staging: wilc1000: Fix kernel Oops on opening the device
   0c4ffbf9e118 iio:chemical:atlas-ph-sensor: Fix use of 32 bit int to hold 16 bit big endian value
   52a1e76f16e2 arm64: dts: marvell: fix clocksource for CP110 master SPI0
   0dff3c6321a5 tty: limit terminal size to 4M chars
   44f0722dc9ac xhci: workaround for hosts missing CAS bit
   0894224ae7c0 xhci: add restart quirk for Intel Wildcatpoint PCH
   b2d28d93cf83 hv: do not lose pending heartbeat vmbus packets
   eeae0a12a166 vt: clear selection before resizing
   9710f5b19328 x86/smpboot: Init apic mapping before usage
   58b0a7f115f8 GenWQE: Fix bad page access during abort of resource allocation
   b9aa0a7290f5 usb: increase ohci watchdog delay to 275 msec
   241208e7b721 usb: renesas_usbhs: add wait after initialization for R-Car Gen3
   00dbeb06292b xhci: use default USB_RESUME_TIMEOUT when resuming ports.
   1e306cd37a66 USB: serial: ftdi_sio: add support for Infineon TriBoard TC2X7
   d082fd105eb9 USB: serial: cp210x: fix tiocmget error handling
   e8bf726705bd USB: serial: fix potential NULL-dereference at probe
   23124735a6f0 usb: gadget: function: u_ether: don't starve tx request queue
   fe4af125085a usb: gadget: udc: atmel: fix endpoint name
   420d16894425 mei: txe: don't clean an unprocessed interrupt cause.
   5d30e8f65073 ubifs: Fix regression in ubifs_readdir()
   b8176cc56bf1 ubifs: Abort readdir upon error
   1755f43e9a90 timers: Lock base for same bucket optimization
   e18ed431d7da timers: Plug locking race vs. timer migration
   b5e3a038997a timers: Prevent base clock corruption when forwarding
   665f7bf33aa8 timers: Prevent base clock rewind when forwarding clock
   0d621c57e739 x86/microcode/AMD: Fix more fallout from CONFIG_RANDOMIZE_MEMORY=y
   e599203f55ad powerpc/64: Fix race condition in setting lock bit in idle/wakeup code
   51d784b54768 powerpc/64: Re-fix race condition between going idle and entering guest
   2c7ff0e5c311 powerpc/mm/radix: Use tlbiel only if we ever ran on the current cpu
   ae150de2d5e0 powerpc: Convert cmp to cmpd in idle enter sequence
   1198fbca645e btrfs: fix races on root_log_ctx lists
   bc720ae2ffab cxl: Fix leaking pid refs in some error paths
   2a997e83960b ANDROID: binder: Clear binder and cookie when setting handle in flat binder struct
   599cfd58ffde ANDROID: binder: Add strong ref checks
   2a0efa30b15c ALSA: hda - Fix headset mic detection problem for two Dell laptops
   2585e17b71c7 ALSA: hda - Fix surround output pins for ASRock B150M mobo
   14456570a4a5 ALSA: hda - Adding a new group of pin cfg into ALC295 pin quirk table
   54186c7dd2ec ALSA: hda - allow 40 bit DMA mask for NVidia devices
   0f574c90d747 ALSA: seq: Fix time account regression
   8ccf154b2654 ALSA: usb-audio: Add quirk for Syntek STK1160
   9d3f5b85ef8b device-dax: fix percpu_ref_exit ordering
   33bcff297228 security/keys: make BIG_KEYS dependent on stdrng.
   5152986c9257 KEYS: Sort out big_key initialisation
   5daa841d0437 KEYS: Fix short sprintf buffer in /proc/keys show function
   0a38e6c551c4 thermal/powerclamp: correct cpu support check
   5db5e0c11c13 mm: memcontrol: do not recurse in direct reclaim
   68adb469dd3b mm/slab: fix kmemcg cache creation delayed issue
   67ae004e2c52 mm/list_lru.c: avoid error-path NULL pointer deref
   5cb73199ca48 libxfs: clean up _calc_dquots_per_chunk
   d00057ecf82f gpio: GPIO_GET_LINE{HANDLE,EVENT}_IOCTL: Fix file descriptor leak
   c70eb2cc1276 gpio: GPIOHANDLE_GET_LINE_VALUES_IOCTL: Fix another information leak
   6bba4b226521 gpio: GPIO_GET_LINEEVENT_IOCTL: Reject invalid line and event flags
   e2144827d96b gpio: GPIO_GET_LINEHANDLE_IOCTL: Reject invalid line flags
   c0699405b147 gpio: GPIO_GET_LINEEVENT_IOCTL: Validate line offset
   49bdfb21e37d gpio: GPIOHANDLE_GET_LINE_VALUES_IOCTL: Fix information leak
   e22edf53b40f gpio: GPIO_GET_LINEHANDLE_IOCTL: Validate line offset
   a23a59c56a53 gpio: GPIO_GET_CHIPINFO_IOCTL: Fix information leak
   78ae767553e4 gpio: GPIO_GET_CHIPINFO_IOCTL: Fix line offset validation
   56ffab4f532e gpio / ACPI: fix returned error from acpi_dev_gpio_irq_get()
   4366246129ca h8300: fix syscall restarting
   a639266ae0c3 spi: mark device nodes only in case of successful instantiation
   d6634d871199 spi: fsl-espi: avoid processing uninitalized data on error
   0cee66b72acc drm/dp/mst: Clear port->pdt when tearing down the i2c adapter
   f2ffb21fb495 i2c: core: fix NULL pointer dereference under race condition
   0fda1cdcbb72 i2c: xgene: Avoid dma_buffer overrun
   9c619c2a8d4d i2c: rk3x: Give the tuning value 0 during rk3x_i2c_v0_calc_timings

(From OE-Core rev: f95903012735e764ae0608a17fc6d4d8c139eb83)

(From OE-Core rev: 02cbbeb726923df8122d5e30a1908a0897e8cd6c)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
c3be679a54 linux-yocto/4.8: update to v4.8.6-rt5
Paul Gortmaker sent along updates to the latest 4.8 -rt version.
Updating the SRCREVs to include the following commits:

   f83a3d4a643b v4.8.6-rt5
   74c7ffc2e3f2 NFSv4: don't disable preemption on !RT
   9711dc408890 kbuild: Add -fno-pie to KBUILD_AFLAGS:
   7b4d4278e307 v4.8.6-rt4
   24aa22031f3c v4.8.2-rt3
   8541163464e2 kbuild: add -fno-PIE
   81b61ced2d45 NFSv4: replace seqcount_t with a seqlock_t
   a8300ce29d0c worqueue: document the proper argument
   9711591ebdc3 genirq: document swork member
   1aace69fd88f rbtree: include barrier.h
   74d4589809f2 rxrpc: remove unused static variables
   a941e2f0611c x86/apic: get rid of "warning: 'acpi_ioapic_lock' defined but not used"
   9888d1c2e3ab hotplug: Call mmdrop_delayed() in sched_cpu_dying() if PREEMPT_RT_FULL
   debf0ec42b2e drivers/zram: Don't disable preemption in zcomp_stream_get/put()
   c84b472ee376 mm/zs_malloc: Fix bit spinlock replacement
   c17de80bfeba zsmalloc: turn that get_cpu_light() into a local_lock()
   33586701e8ad connector/cn_proc: Protect send_msg() with a local lock on RT
   b20867d36bcd ftrace: Fix trace header alignment

(From OE-Core rev: 6840594c43b892056886f471575ccb49a78f34e4)

(From OE-Core rev: 0ec50af0cbc8c3fc6301637e4efeaf99fea0512e)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
02bfc6a0dc linux-yocto/4.1: update to v4.1.35
Updating to the korg -stable release.

(From OE-Core rev: c0231b1306034cc03987a5fbabd6f17125c9392b)

(From OE-Core rev: b4b0a4232cf4bd22a4cb0941998c6f66429a23b8)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
6a25e7a5fd linux-yocto/4.4: update to v4.4.30
Updating to the korg -stable release.

(From OE-Core rev: feed13b4d108a93b4e95ed9f80f9624e1bd1cdf5)

(From OE-Core rev: a916135b282e1a350a380b96eb0b04d2820bea6e)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
da9ceffa9e linux-yocto/4.8: fix cryptodev compilation error
It was reported that compilation was broken for the in tree variant of
cryptodev. This commit integrates two patches that fix the issue:

  efbdfa1ed95f cryptodev: stomp dynamic version numbering for in tree builds
  32f54070205f cryptodev: fix compile error when enable CONFIG_CRYPTODEV

(From OE-Core rev: b91469ac21825a86eb7a71f1e91206719061bcaa)

(From OE-Core rev: 4ce2375e4ef1ef37e87c95faa0cae6171f390afa)

Signed-off-by: Liwei Song <liwei.song@windriver.com>
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Bruce Ashfield
7033e66e9f linux-yocto/4.8: update to 4.8.6
Integrating the korg -stable release.

(From OE-Core rev: 2a7d3173c7a05cd09bbcf5fe465403b2d4b2b589)

(From OE-Core rev: f805e0c996342b1171035792bcc06d90026d5e5f)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Ross Burton
3c9a34aaea conf: add C++ flags for uninative interoperatility
Create a common include file for compiler flags which allow native binaries to
be interoperable on a wide range of hosts. In particular the C++ ABI is
problematic so choose the CXX11 version to allow interoperation between gcc4 and
gcc5 based hosts. Moving this to a common include instead of uninative.bbclass
allows uninative to be configured later and used in the eSDK (where its
mandatory) even if the base configuration doesn't enable uninative by default
(e.g. nodistro in OE-Core).

[ YOCTO #10645 ]

(From OE-Core rev: 60c912ae9306532bdd4c5e09a65863ee77c12f43)

(From OE-Core rev: 10dea25aac31c156350e3e73f937472404c22d81)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Fabio Berton
91ec543003 binutils: Fix build for c293pcie PPC machine
The following patch fix build for c293pcie PPC machine :
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=8941017b

This patch is a backport from master branch.

Fix error:
/
|ERROR: binutils-2.27-r0 do_package: runstrip: ''powerpc-fslc-linux-gnuspe-strip'
|--remove-section=.comment --remove-section=.note --strip-unneeded
|'../tmp/work/ppce500v2-fslc-linux-gnuspe/binutils/2.27-r0/package/usr/lib/
|libbfd-2.27.0.20160806.so'' strip command failed with 1
|(b'powerpc-fslc-linux-gnuspe-strip: ../tmp/work/ppce500v2-fslc-linux-gnuspe/
|binutils/2.27-r0/package/usr/lib/stJMAEnm: Not enough room for program headers,
|try linking with -N\npowerpc-fslc-linux-gnuspe-strip:../tmp/work/
|ppce500v2-fslc-linux-gnuspe/binutils/2.27-r0/package/usr/lib/stJMAEnm
|[.note.gnu.build-id]: Bad value\n')
\

(From OE-Core rev: 3526c23ae98d2e08af20b77175c12907355ec42a)

(From OE-Core rev: 639b1b6d187ee44b3f67b9d013517a0c904fffc4)

Signed-off-by: Fabio Berton <fabio.berton@ossystems.com.br>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Maciej Borzecki
d6f478d9df wic: fix function comment typos
Fix typos in documentation of Image.add_partition() and
Image.__format_disks().

(From OE-Core rev: f5bf7bf253224912c66bab89f48ff63a73e0d698)

(From OE-Core rev: 44ce5b4bb0873d5a2dec25f2dc489a6ab8f7995e)

Signed-off-by: Maciej Borzecki <maciej.borzecki@rndity.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Maciej Borzecki
0a25fbfdb4 wic: check that filesystem is specified for a rootfs partition
We explicitly check for --fstype if no source was provided for a
partition. However, this was not the case for rootfs partitions. Make
sure to raise an error if filesystem was left unspecified when preparing
a rootfs partition image.

(From OE-Core rev: b8c35fcad57810a87aa25ebeb533adf286eed565)

(From OE-Core rev: dc4d1cfc4d6bd01432857448f66af5492cad7574)

Signed-off-by: Maciej Borzecki <maciej.borzecki@rndity.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Maciej Borzecki
0c5596e5d3 wic: make sure that partition size is always an integer in internal processing
The size field of Partition class is expected to be an integer and ought
to be set inside prepare_*() method. Make sure that this is always the
case.

(From OE-Core rev: a37838f995ae642b0b8bdd47a605a264fb3bf200)

(From OE-Core rev: 4e869343952aef8748b40e538c14ad8b94221910)

Signed-off-by: Maciej Borzecki <maciej.borzecki@rndity.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:42 +00:00
Yi Zhao
25cd713c44 tiff: Security fix CVE-2016-3632
CVE-2016-3632 libtiff: The _TIFFVGetField function in tif_dirinfo.c in
LibTIFF 4.0.6 and earlier allows remote attackers to cause a denial of
service (out-of-bounds write) or execute arbitrary code via a crafted
TIFF image.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3632
http://bugzilla.maptools.org/show_bug.cgi?id=2549
https://bugzilla.redhat.com/show_bug.cgi?id=1325095

The patch is from RHEL7.

(From OE-Core rev: 9206c86239717718be840a32724fd1c190929370)

(From OE-Core rev: 0c6928f4129e5b1e24fa2d42279353e9d15d39f0)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Yi Zhao
abcb751f02 nfs-utils: fix protocol minor version fall-back
Mount nfs directory would fail if no specific nfsvers:
mount -t nfs IP:/foo/bar/ /mnt/
mount.nfs: an incorrect mount option was specified

mount.nfs currently expects mount(2) to fail with EPROTONOSUPPORT if
the kernel doesn't understand the requested NFS version.
Unfortunately if the requested minor is not known to the kernel
it returns -EINVAL.

Backport patch from nfs-utils-1.3.4 to fix this issue.

(From OE-Core rev: 332596628697d28ae6e8c2271c9658aaf5e54796)

(From OE-Core rev: 2b8362c42f9a7d689084ad956370d2d6c4fa9179)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Yi Zhao
ebbaae9005 openssl: Security fix CVE-2016-7055
There is a carry propagating bug in the Broadwell-specific Montgomery
multiplication procedure that handles input lengths divisible by, but
longer than 256 bits.

External References:
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-7055
https://www.openssl.org/news/secadv/20161110.txt

Patch from:
57c4b9f6a2

(From OE-Core rev: 07cfa9e2bceb07f3baf40681f8c57f4d3da0aee5)

(From OE-Core rev: 090c2ff292a4d92142c3f33c7517be69d9c16c24)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
T.O. Radzy Radzykewycz
545a4d2e56 OpenSSL: CVE-2004-2761 replace MD5 hash algorithm
Use SHA256 as default digest for OpenSSL instead of MD5.

CVE: CVE-2004-2761

    The MD5 Message-Digest Algorithm is not collision resistant,
    which makes it easier for context-dependent attackers to
    conduct spoofing attacks, as demonstrated by attacks on the
    use of MD5 in the signature algorithm of an X.509 certificate.

Upstream-Status: Backport
Backport from OpenSSL 2.0 to OpenSSL 1.0.2
Commit f8547f62c212837dbf44fb7e2755e5774a59a57b

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
(From OE-Core rev: f924428cf0c22a0b62769f8f31f11f173f25014f)

(From OE-Core rev: 0066e5c5559009f250b6e5953d5830db2c8769e1)

Signed-off-by: Zhang Xiao <xiao.zhang@windriver.com>
Signed-off-by: T.O. Radzy Radzykewycz <radzy@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Khem Raj
8325c93df9 cmake.bbclass: Set CXXFLAGS and CFLAGS
We strip the TOOLCHAIN_OPTIONS and HOST_CC_ARCH from CC/CXX in cmake.bbclass
whereas CFLAFS and CXXFLAGS assume that TOOLCHAIN_OPTIONS are
part of CC/CXX variables, this causes compile failures when cmake
is running compiler tests during configure on some architectures
especially armhf, because hf ABI information -mfloat-abi is part
of TOOLCHAIN_OPTIONS, so what happens is that testcase gets compiled
without hard-float, howver, during linking the float ABI option
is passed via LDFLAGS, now linker rejects this and fails like
/mnt/a/build/tmp-glibc/sysroots/x86_64-linux/usr/libexec/arm-oe-linux-gnueabi/gcc/arm-oe-linux-gnueabi/6.2.0/ld: error: cmTC_27947 uses VFP register arguments, CMakeFiles/cmTC_27947.dir/src.cxx.o does not
mnt/a/build/tmp-glibc/sysroots/x86_64-linux/usr/libexec/arm-oe-linux-gnueabi/gcc/arm-oe-linux-gnueabi/6.2.0/ld: failed to merge target specific data of file CMakeFiles/cmTC_27947.dir/src.cxx.o
collect2: error: ld returned 1 exit status

This means that CMake now fails the configure time test too
which is not right, e.g. it might disable features which actually do exist
and should be enabled e.g. in case above it is resulting as below

Performing C++ SOURCE FILE Test HAS_BUILTIN_SYNC_SUB_AND_FETCH failed with the following output:

Its actually a bug in CMake see
https://gitlab.kitware.com/cmake/cmake/issues/16421

CMake is ignoring CMAKE_CXX_FLAGS when using CHECK_CXX_SOURCE_COMPILES
function.

Until it is fixed upstream, we add HOST_CC_ARCH and TOOLCHAIN_OPTIONS
to CFLAGS and CXXFLAGS, so that we can ensure that compiler invocation
remains consistent.

(From OE-Core rev: 826f3cdb474b5728b22f08d2342fc90235ca9e7d)

(From OE-Core rev: 7e5fd5914e15397a56425130c2322ace67da2ee4)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Zhixiong Chi
cb2967921e tiff: Security fix CVE-2016-3658
The TIFFWriteDirectoryTagLongLong8Array function in tif_dirwrite.c in the tiffset tool
allows remote attackers to cause a denial of service (out-of-bounds read) via vectors
involving the ma variable.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3658
http://bugzilla.maptools.org/show_bug.cgi?id=2546

Patch from:
45c68450be

(From OE-Core rev: c060e91d2838f976774d074ef07c9e7cf709f70a)

(From OE-Core rev: cc266584158c8dfc8583d21534665b6152a4f7ee)

Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Kai Kang
460bbf456b qemu: update run-ptest script
The Makefile in directory tests has been renamed, then update script
run-ptest to follow the change.

(From OE-Core rev: 364565f3f3baccc9757ce0dcb393464b38055b4f)

(From OE-Core rev: aece2afafbd304adee30978537b9404a9344dd4e)

Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Kai Kang
8d1afc2a0d qemu: fix CVE-2016-7909
Backport patch to fix CVE-2016-7909 of qemu.

Ref:
https://security-tracker.debian.org/tracker/CVE-2016-7909

(From OE-Core rev: 126783ca25a5ae9daf87ac563239fbff4696a682)

(From OE-Core rev: 469267010b43a1c114e22009c9ac68f36c22f896)

Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
André Draszik
31d4000b15 openssl: fix bashism in c_rehash shell script
This script claims to be a /bin/sh script, but it uses
a bashism:

from checkbashisms:

possible bashism in meta/recipes-connectivity/openssl/openssl/openssl-c_rehash.sh line 151 (should be 'b = a'):
	    if [ "x/" == "x$( echo ${FILE} | cut -c1 -)" ]

This causes build issues on systems that don't have
/bin/sh symlinked to bash:

Updating certificates in ${WORKDIR}/rootfs/etc/ssl/certs...
<builddir>/tmp/sysroots/x86_64-linux/usr/bin/c_rehash: 151: [: x/: unexpected operator
 ...

Fix this by using POSIX shell syntax for the comparison.

(From OE-Core rev: 0526524c74d4c9019fb014a2984119987f6ce9d3)

(From OE-Core rev: 2ece9c0e955ee99543968ddfd14da909e23ae611)

Signed-off-by: André Draszik <adraszik@tycoint.com>
Reviewed-by: Sylvain Lemieux <slemieux@tycoint.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Ross Burton
a469b6efc6 systemtap: fix native linking on recent Ubuntu
The latest Ubuntu uses yet more aggressive hardening options, which causes the
unconventional build order used by systemtap to fail.

[ YOCTO #10521 ]

(From OE-Core rev: 5ca6ac8739ea4a273df7b8e5c5f7d481619923d8)

(From OE-Core rev: 3397af5877a41a6a59aeb90f8610c759cad38795)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Ross Burton
6d57ce3fa3 systemtap: remove explicit msgfmt check
Passing --disable-nls should be enough to disable the requirement for a full
gettext to be present, but the upstream configure explicitly checks for msgfmt
even if it isn't going to be used.  To avoid having to depend on gettext-native,
patch this check out.

(From OE-Core rev: 2f8d2a74f73490c1ae35131d3eb3592f7ee0a1e4)

(From OE-Core rev: 7d689876574ba47e5ad07d67ad40fd865b0c27f5)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Ed Bartosh
c852c9352f systemd-bootdisk.wks: use PARTUUID
Root device name in systemd-bootdisk.wks is 'sda'. This can cause
images, produced using this wks to refuse booting if real device
name is not 'sda'. For example, when booting MinnowBoard MAX from
MicroSD card the boot process stucks with this message on the boot
console output: Waiting for root device /dev/sda2...
This happens because real device name of MicroSD card on this device
is mmcblk1.

Used --use-uuid option for root partition. This should make
wic to put partiion UUID instead of device name into kernel command
line.

[YOCTO #10485]

(From OE-Core rev: 5b73d5f484cc844affe91ec19d881d42e187f30c)

(From OE-Core rev: 71a365d57359dd8d9bfce66985975b1533e983d7)

Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Khem Raj
c0526ab007 libbsd: Fix build with musl
a.out.h support is not across all architectures only
x86/x86_64 support is in linux/a.out.h, this patch
abstracts the minimum needed constructs into itself

(From OE-Core rev: 757224640bbf4ebf17aea22fa1419c9c3bcd89ce)

(From OE-Core rev: 7985b295384f98fd6ea88f3aff197ccf0369977b)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Li Zhou
1a118330c3 db: disable the ARM assembler mutex code
The swpb in macro MUTEX_SET will cause "undefined instruction" error
on the new arm arches which don't support this assembly instruction
any more. If use ldrex/strex to replace swpb, the old arm arches don't
support them. So to avoid this issue, just disable the ARM assembler
mutex code, and use the default pthreads mutex.

(From OE-Core rev: aafbc548ebc66dc0d703526f9a98f784e9c9605b)

(From OE-Core rev: d6a0ef7e9dfbda3d55ba18f2bcc69f04d502495d)

Signed-off-by: Li Zhou <li.zhou@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
André Draszik
53ad465b40 cve-check.bbclass: CVE-2014-2524 / readline v5.2
Contrary to the CVE report, the vulnerable trace functions
don't exist in readline v5.2 (which we keep for GPLv2+
purposes), they were added in readline v6.0 only - let's
whitelist that CVE in order to avoid false positives.

See also the discussion in
 https://patchwork.openembedded.org/patch/81765/

(From OE-Core rev: b881a288eec598002685f68da80a24e0478fa496)

(From OE-Core rev: b4498a6b734661fdfe3ff4e0a9850e796b72005c)

Signed-off-by: André Draszik <adraszik@tycoint.com>
Reviewed-by: Lukasz Nowak <lnowak@tycoint.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Robert Yang
2336faa9aa qemuarm64.conf: make runqemu's graphics work
Fixed:
$ runqemu qemuarm64 (without -nographics)
There is no output in qemu console without this fix.

(From OE-Core rev: 40a64e64b2ff41661ff254d0836c5f60120c6795)

(From OE-Core rev: f07c139e91d2173dac4289727d1401a19d6ed821)

Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Daniel Díaz
a4c7f45b8b weston: Add no-input-device patch to 1.11.0.
The included patch, backported from Weston master (and OE-Core
master since Weston 1.11.1, b6864b1), allows it to run without
any input device at launch. An ini option is introduced for
this purpose, so there is no behavioral change.

Related change in weston.ini:
  [core]
  require-input=true

Default is true; setting it false allows Weston to run
without a keyboard or mouse, which is handy for automated
environments.

(From OE-Core rev: 8fa5e442d16b1d04066b51b9fd56be41ae67d2d5)

Signed-off-by: Daniel Díaz <daniel.diaz@linaro.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Koen Kooi
6b736febdc libbsd 0.8.3: BBCLASSEXTEND to native and nativesdk
Android-tools depends on it and to build the native versions of fastboot, adb, mkbootimg and others libbsd needs to support native builds.

(From OE-Core rev: 5d6761dacd370fdb6f29269a22cfbca86f301024)

Signed-off-by: Koen Kooi <koen.kooi@linaro.org>
Signed-off-by: Ross Burton <ross.burton@intel.com>
(cherry picked from commit b02cef58ee35dd277fff48538ce2803df1cbc4d5)
Signed-off-by: Nicolas Dechesne <nicolas.dechesne@linaro.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Armin Kuster
4c1020aad6 tzdata: update to 2016i
Briefly: Cyprus split into two time zones on 2016-10-30, and Tonga
  reintroduces DST on 2016-11-06.

  Changes to future time stamps

    Pacific/Tongatapu begins DST on 2016-11-06 at 02:00, ending on
    2017-01-15 at 03:00.  Assume future observances in Tonga will be
    from the first Sunday in November through the third Sunday in
    January, like Fiji.  (Thanks to Pulu ʻAnau.)  Switch to numeric
    time zone abbreviations for this zone.

  Changes to past and future time stamps

    Northern Cyprus is now +03 year round, causing a split in Cyprus
    time zones starting 2016-10-30 at 04:00.  This creates a zone
    Asia/Famagusta.  (Thanks to Even Scharning and Matt Johnson.)

    Antarctica/Casey switched from +08 to +11 on 2016-10-22.
    (Thanks to Steffen Thorsen.)

  Changes to past time stamps

    Several corrections were made for pre-1975 time stamps in Italy.
    These affect Europe/Malta, Europe/Rome, Europe/San_Marino, and
    Europe/Vatican.

    First, the 1893-11-01 00:00 transition in Italy used the new UT
    offset (+01), not the old (+00:49:56).  (Thanks to Michael
    Deckers.)

    Second, rules for daylight saving in Italy were changed to agree
    with Italy's National Institute of Metrological Research (INRiM)
    except for 1944, as follows (thanks to Pierpaolo Bernardi, Brian
    Inglis, and Michael Deckers):

      The 1916-06-03 transition was at 24:00, not 00:00.

      The 1916-10-01, 1919-10-05, and 1920-09-19 transitions were at
      00:00, not 01:00.

      The 1917-09-30 and 1918-10-06 transitions were at 24:00, not
      01:00.

      The 1944-09-17 transition was at 03:00, not 01:00.  This
      particular change is taken from Italian law as INRiM's table,
      (which says 02:00) appears to have a typo here.  Also, keep the
      1944-04-03 transition for Europe/Rome, as Rome was controlled by
      Germany then.

      The 1967-1970 and 1972-1974 fallback transitions were at 01:00,
      not 00:00.

(From OE-Core rev: daf95f7fd9f7ab65685d7b764d8e50df8d00d308)

(From OE-Core rev: 550901db388eda2476da24b71117223be999688b)

Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Armin Kuster
afaef2018f tzcode: update to 2016i
Changes to code

  The code should now be buildable on AmigaOS merely by setting the
  appropriate Makefile variables.  (From a patch by Carsten Larsen.)

(From OE-Core rev: d2b8c4ee535684f5d874082a7f76efbda1907ea5)

(From OE-Core rev: 757f2cb2f2acaf41d3f81c5b9bb0afd8e05001db)

Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:41 +00:00
Kai Kang
724fa5a489 openssh: fix CVE-2016-8858
Backport patch to fix CVE-2016-8858 of openssh.

Ref:
https://bugzilla.redhat.com/show_bug.cgi?id=1384860

(From OE-Core rev: 134a05616839d002970b2e7124ea38348d10209b)

(From OE-Core rev: 07e289d7212d6343370bfc883631a19f37bc85f1)

Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:40 +00:00
Ross Burton
101173d6cf lib/oe/qa: handle binaries with segments outside the first 4kb
The ELF parser was assuming that the segment tables are in the first 4kb of the
binary.  Whilst this generally appears to be the case, there have been instances
where the segment table is elsewhere (offset 2MB, in this sample I have).  Solve
this problem by mmap()ing the file instead.

Also clean up the code a little whilst chasing the problem.

(From OE-Core rev: b88c6bd61e7c3388b3902de1adb5e48a88f2e235)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:40 +00:00
Ross Burton
b0b646ab3c Revert "epiphany: remove unnecessary libwnck3 dependency"
This version of epiphany still needs libwnck3.

This reverts commit fb5c4f181176710a4cfb3c875b5edb4e5aa5df73.

(From OE-Core rev: eec53627ac5c3aa811a0bd97f06a4827ef0189d3)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:40 +00:00
Ross Burton
7dc792da69 Revert "libwnck3: remove the recipe"
The epiphany in morty still needs libwnck3, so bring it back.

This reverts commit 129281e8557ec8d29ecf863675884713a3050f4b.

(From OE-Core rev: d09108805dab4595101706f6e75a0a622d3b0cda)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2017-01-11 17:21:40 +00:00
Scott Rifenbark
5aa481dfed ref-manual: Added KERNEL_IMAGE_BASE_NAME change to 2.2 migration
The fact that the OpenEmbedded build system can now build
multiple image types caused the KERNEL_IMAGE_BASE_NAME variable
to have the KERNEL_IMAGETYPE portion removed.  This could cause
existing recipes that use the KERNEL_IMAGE_BASE_NAME variable
directly issues.  I added a section indicating that the user
should address those recipes to avoid problems.

(From yocto-docs rev: 2b4a36b45846e296c15d62ee8fabdd9ff29b2b0f)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-12-08 16:36:47 +00:00
Scott Rifenbark
872d4bccc8 ref-manual: Updated KERNEL_IMAGE_BASE_NAME glossary description
Fixes [YOCTO #10717]

Now that multiple images can be built, the KERNEL_IMAGE_BASE_NAME
no longer requires "${KERNEL_IMAGETYPE}" as part of its default
value.  I have removed this portion of the default definition
described in the glossary.

(From yocto-docs rev: 54abeb3fbbac8b6d319183f88803fbe71b27fcbe)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-12-08 16:36:47 +00:00
Scott Rifenbark
d9e3f7629b dev-manual: Added note about RPM not dealing with post-install
Fixes [YOCTO #10351]

I added a note to the "Post Installation Scripts" section of the
"Writing a New Recipe" section to call out the fact that the
RPM package manager will not install packages on the target when
any RPM post-install script returns a non-zero exit code when
the script is run on the target.

(From yocto-docs rev: a2b36b4a352522e3c576a45ee239af51eda518c1)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-12-08 16:36:47 +00:00
Scott Rifenbark
2a6bba4378 ref-manual, dev-manual: Added references to SYSROOT_DIRS
Fixes [YOCTO #10692]

I updated the STAGING_DIR variable description to have a reference
to the SYSROOT_DIRS variable as well as the "Sharing Files
Between Recipes" section of the dev-manual.

I also updated the "Sharing Files Between Recipes" section so
that the role of SYSROOT_DIRS is explained and actually used
in an example to add another directory.

(From yocto-docs rev: 23114b4bc708398bae8c4559793dd36bc53c96a2)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-12-08 16:36:47 +00:00
Scott Rifenbark
e56cd9d7d0 sdk-manual: Updated the section on adding docs to standard SDK
Fixes [YOCTO #8584]

Made some edits to tighten this down and make it more efficient.

(From yocto-docs rev: f25c0cf08877b62a6e2523b5d4caa83c008ef004)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-12-08 16:36:47 +00:00
brian avery
73454473d7 bitbake: toaster: settings set ALLOWED_HOSTS to * in debug mode
As of Django 1.8.16, Django is rejecting any HTTP_HOST header that is
not on the ALLOWED_HOST list.  We often need to reference the
toaster server via a fqdn, if we start it via webport=0.0.0.0:8000 for
instance, and are hitting the server from a laptop. This change does
reduce  the protection from a DNS rebinding attack, however, if you are
running the toaster server outside a protected network, you should be
using the production instance.

[YOCTO #10578]

(Bitbake rev: 59a3f391ac5ac194f30d11a39676356464269d55)

Signed-off-by: brian avery <brian.avery@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 11:38:51 +00:00
Scott Rifenbark
ee6fb7521b documentation: Added new appendix for customizing standard SDK
Fixes [YOCTO #8584]

This fix essentially had to document how to add the API
documentation to the standard SDK.  The fix required adding a
new appendix to the SDK manual on how to customize that
standard SDK.  I could not put just one topic in a new appendix
so I also added a sub-section on how to add indidual packages
to the standard SDK.

Other changes here were the introduction of a new file for the new
appendix, updated the mega-manual.xml file so that it would include
the new chapter when the MM was built.  Finally, I added some
cross-referencing to the new appendix from the TOOLCHAIN_HOST_TASK
and TOOLCHAIN_TARGET_TASK variables.  And a cross reference from the
distro features section on the api-documentation bullet.

(From yocto-docs rev: d2b5224df82959e0ce52d12f579a572b86f9fc70)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:38:35 +00:00
Scott Rifenbark
6f33cfec73 ref-manual: Added api-documentation to distro features
Fixes [YOCTO #8584]

Updated the "Distro Features" section to include the
"api-documentation" feature.

(From yocto-docs rev: ad02528f13390c2c0dc5717c1f9088212def37be)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:38:35 +00:00
Scott Rifenbark
e706bc85a7 dev-manual: Fixed typo for "${INC_PR}.0"
The string appeared in the text as "$(INC_PR).0".  So, fixed
it to be proper with the curly braces.

(From yocto-docs rev: 113296272e60da09c88660d09a5e8ba06f0fda7a)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:38:35 +00:00
Scott Rifenbark
0de5f9472d ref-manual: Fixed presentation of "openSUSE" in supported distros
The way I had this string was incorrect.  I changed it to "openSUSE".

(From yocto-docs rev: 1b44f58f7cf9c68186dd271b4779b3a368757b1d)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:38:35 +00:00
Scott Rifenbark
047790941e ref-manual: Updated the RDEPENDS variable description.
Fixes [YOCTO #10445]

Pointed out that the EXTENDPKGV variable is hard to locate in the
BB manual.  Firstly, we don't document that variable in the
BB manual.... maybe we should.  For the ref-manual, however, it is
barely referenced in a side example from the dev-manual.  So, I
updated the RDEPENDS variable to have a "Tip" box in the area where
it is shown how to use the package version as part of the RDEPENDs
variable.

(From yocto-docs rev: f42525ba8a4d20722d15c9fa250c494a90ff478b)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:38:35 +00:00
Scott Rifenbark
0a22517801 dev-manual: Updated "Exporting Tests" section
Fixed [YOCTO #10588]

This section was confusing due to the fact that it used an actual
set of IP addresses and image name where they should be clearly
called out as examples.  Fixed it.

(From yocto-docs rev: 006a25fad282b03aacd59eb8dc1a44cad2c19fc4)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Scott Rifenbark
38366d30fc ref-manual: Updated the supported distro list for Morty.
(From yocto-docs rev: 8643b19b096039f321b85dbaf1f68c7d3c26f791)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Scott Rifenbark
71f907cbe1 yocto-project-qs: Fixed typo
Fixes [YOCTO #10451]

Added a missing closing parentheses to a sentence.

(From yocto-docs rev: 8fc10d592eb426c5b173be2280b72fa7ccf3510c)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Scott Rifenbark
604a71f7c0 ref-manual: Fixed tense issue for migration 2.2 section
The "runqemu Ported to Python" section was using past tense
for a note about previous usage patterns being supported.  I
changed this to present tense.

(From yocto-docs rev: 15aa9d5a0164fa9553cf252a651d6aa5fb1c23f0)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Scott Rifenbark
56238f3676 yocto-project-qs: Fixed the minnowboard example to use .wic and base
(From yocto-docs rev: 072ac7943ddcefd90ec36ee74a8571adf2cefb1b)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Markus Lehtonen
feb145f6ce bitbake: bitbake-worker: print full traceback instead of message only
Print full traceback instead of just the exception message in the
child() function inside fork_off_task(). This makes debugging a lot
easier as the function catches a generic "Exception" and the exception
message alone might not give much information.

[YOCTO #10393]

(Bitbake rev: 61cc397a5b7136afb37052a2860c6c39a176ddab)

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Markus Lehtonen
8472ed0c89 bitbake: data: fix exception handling in exported_vars()
Fix a bug where a totally wrong value of a variable would be exported if
an exception happened during d.getVar(). Also, print a warning if an
exception happends instead of silently ignoring it. It would probably be
best just to raise the exception, instead, but use the warning for now
in order to avoid breaking existing builds.

[YOCTO #10393]

(Bitbake rev: 59c606cfc6e0a4f367344d4e3def6017fb560d75)

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Richard Purdie
a34582a85e bitbake: siggen: Ensure taskhash mismatches don't override existing data
We recalculate the taskhash to ensure the version we have matches
what we think it should be. When we write out a sigdata file, use
the calculated value so that we don't overwrite any existing file.
This leaves any original taskhash sigdata file intact to allow a
debugging comparison.

(Bitbake rev: dac68af6f4add9c99cb7adcf23b2ae89b96ca075)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Richard Purdie
f17446b645 bitbake: siggen: Pass basehash to worker processes and sanity check reparsing result
Bitbake can parse metadata in the cooker and in the worker during builds. If
the metadata isn't deterministic, it can change between these two parses and
this confuses things a lot. It turns out to be hard to debug these issues
currently.

This patch ensures the basehashes from the original parsing are passed into
the workers and that these are checked when reparsing for consistency. The user
is shown an error message if inconsistencies are found.

There is debug code in siggen.py (see the "Slow but can be useful for debugging
mismatched basehashes" commented code), we don't enable this by default due to
performance issues. If you run into this message, enable this code and you will
find "sigbasedata" files in tmp/stamps which should correspond to the hashes
shown in this error message. bitbake-diffsigs on the files should show which
variables are changing.

(Bitbake rev: 46207262ee6cdd2e49c4765481a6a24702ca4843)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Richard Purdie
aea27a0554 bitbake: build: Ensure we preserve sigbasedata files as well as sigdata ones
We don't remove sigdata files, we also shouldn't remove sigbasedata files
as this hinders debugging.

(Bitbake rev: 06e7c00f2e1ddda6a2632ec2354a3c8f5c34562d)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Richard Purdie
350df1de9c rm_work: Ensure we don't remove sigbasedata files
We don't remove sigdata files, we also shouldn't remove sigbasedata files
as this hinders debugging.

(From OE-Core rev: 988349f90c8dc5498b1f08f71e99b13e928a0fd0)

(From OE-Core rev: c8d96b10ee3bc2eae0fd269d2564286fd0bc82ed)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Richard Purdie
350a850d44 sstate: Ensure we don't remove sigbasedata files
We don't remove sigdata files, we also shouldn't remove sigbasedata files
as this hinders debugging.

(From OE-Core rev: 1ebd85f8dfe45b92c0137547c05e013e340f9cec)

(From OE-Core rev: 3764a5ce8a1f26b46c389c256c10596ed8d31cc7)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Andre McCurdy
87d51bd79b gdb: update 7.11+git1a982b689c -> 7.11.1
41d8236 Set GDB version number to 7.11.1.
  136613e Fix PR gdb/19828: gdb -p <process from a container>: internal error
  a0de87e Make gdb/linux-nat.c consider a waitstatus pending on the infrun side
  cf2cd51 Add mi-threads-interrupt.exp test (PR 20039)
  f0a8d0d Fix double prompt output after run control MI commands with mi-async on (PR 20045)
  b5f0db4 Fix -exec-run not running asynchronously with mi-async on (PR gdb/18077)
  7f8e34d Use target_terminal_ours_for_output in MI

(From OE-Core rev: 371345c0dc49bf781c27aea1e9f6a4c947fa30e6)

(From OE-Core rev: 23a7c411b39eece9c80e1fde84894c75ca8dcbe0)

Signed-off-by: Andre McCurdy <armccurdy@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Dengke Du
d16356eb26 subversion: fix "svnadmin create" fail on x86
When run the following command on x86:

        svnadmin create /var/test_repo

It cause segmentation fault error like the following:

        [16499.751837] svnadmin[21117]: segfault at 83 ip 00000000f74bf7f6 sp 00000000ffdd9b34 error 4 in libc-2.24.so[f7441000+1af000]
        Segmentation fault (core dumped)

This is because in source code ./subversion/libsvn_fs_fs/low_level.c,
function svn_fs_fs__unparse_footer, when:

        target arch:    x86
        apr_off_t:      4 bytes

if the "APR_OFF_T_FMT" is "lld", it still use type "apr_off_t" to pass
data to apr, but in apr source code file apr_snprintf.c the function
apr_vformatter meet "lld", it would use the:

        i_quad = va_arg(ap, apr_int64_t);

It uses the apr_int64_t to deal data, it read 8 bytes, so the follow-up
data may be error.

(From OE-Core rev: 7ea7e3db7801b58495b89a95ec2751d618d3a29f)

(From OE-Core rev: 81b9ac05bdb3dc89c6fd17acbfff7cc4f4685108)

Signed-off-by: Dengke Du <dengke.du@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Paul Eggleton
a531ca4636 classes/populate_sdk_ext: prevent invalid TEMPLATECONF entering eSDK
If you are using a repository which contains a .templateconf file that
sets TEMPLATECONF to point into a layer it contains, but you aren't
using that layer in your bblayers.conf, the eSDK would produce an error
during the preparation step of the installation. An example would be
using the poky repository but setting DISTRO to your own custom distro
and removing meta-poky from your bblayers.conf. The eSDK doesn't
support creating new build directories, so we don't care about the
templates and can thus force a known good value to prevent this from
happening.

Fixes [YOCTO #10568].

(From OE-Core rev: 5ee32191a18013061dfa72e64713a94c5d321496)

(From OE-Core rev: 7fbc086f47ef6e36c819836deaa1b2fb3f0ec97a)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
Paul Eggleton
8d1d9cfdb5 oe-setup-builddir: fix TEMPLATECONF error message
This directory shouldn't contain local.conf and bblayers.conf - just
templates for them; except it doesn't have to contain those, it just has
to exist to pass this test. Change the error message accordingly, and
mention TEMPLATECONF so that the user has at least some context.

(From OE-Core rev: 61adaaa4348c670769f8750223977dbefe369ffb)

(From OE-Core rev: 3136666fee621d94ec4c48e706f0dad3b6b6f08c)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:58 +00:00
André Draszik
c2fd90f245 bash_3.2.x: update recipe version to match what we're shipping
Make sure the recipe version matches what we're
actually shipping, so that tools like cve-check
can do the right thing.

Rather than fetching version 3.2.48 and applying all
patches up to and including version 3.2.57, we just
fetch the latter in the first place.

(From OE-Core rev: 614ac87f2832c5359f371439559be88d6106cd6b)

(From OE-Core rev: db3f5330d7a38bb07aca0d65aa94ca36beb721d6)

Signed-off-by: André Draszik <adraszik@tycoint.com>
Acked-by: Sylvain Lemieux <slemieux@tycoint.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Kai Kang
0572d73d11 qemu: fix CVE-2016-7423 and CVE-2016-7908
Backport patches to fix CVE-2016-7423 and CVE-2016-7908 of qemu.

(From OE-Core rev: 1f4c303fd64a4bc05882de01676f241f0df6da78)

(From OE-Core rev: 34b9be55c31deb4eab5056cf1698c8052aca2596)

Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Kai Kang
1bad6c2d73 qemu: supplementary fix of CVE-2016-5403
It is reported in qemu community that VM always exits with:

| 2016-10-17T07:33:40.393592Z qemu-kvm: Virtqueue size exceede

when VM is suspend and resume. Solution from the maintainer of virtio
is to merge following 3 commits:

http://git.qemu.org/?p=qemu.git;a=commit;h=bccdef6
http://git.qemu.org/?p=qemu.git;a=commit;h=58a83c6
http://git.qemu.org/?p=qemu.git;a=commit;h=4b7f91e

The first 2 commits have been merged in qemu 2.7.0. Then apply the
third one.

(From OE-Core rev: db5b9254fbbc30e50b50c7c8cd1f04dcc965cd52)

(From OE-Core rev: 7fa650825957257e6f99d44907c65fd46875125c)

Signed-off-by: Kai Kang <kai.kang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Robert P. J. Day
f068277f90 oe-pkgdata-util: Use standard verb form in help info.
"Shows" -> "Show", to be consistent with standard form of help output.

(From OE-Core rev: 5a7994df6cdb5af8d240e2802e6bb3d9671f17e3)

(From OE-Core rev: 417ee79d97b0f016c4b55c49690107d541cfc250)

Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Armin Kuster
ff95390bee tzdata: Update to 2016h
Changes to future time stamps

    Asia/Gaza and Asia/Hebron end DST on 2016-10-29 at 01:00, not
    2016-10-21 at 00:00.  (Thanks to Sharef Mustafa.)  Predict that
    future fall transitions will be on the last Saturday of October
    at 01:00, which is consistent with predicted spring transitions
    on the last Saturday of March.  (Thanks to Tim Parenti.)

Changes to past time stamps

    In Turkey, transitions in 1986-1990 were at 01:00 standard time
    not at 02:00, and the spring 1994 transition was on March 20, not
    March 27.  (Thanks to Kıvanç Yazan.)

Changes to past and future time zone abbreviations

    Asia/Colombo now uses numeric time zone abbreviations like "+0530"
    instead of alphabetic ones like "IST" and "LKT".  Various
    English-language sources use "IST", "LKT" and "SLST", with no
    working consensus.  (Usage of "SLST" mentioned by Sadika
    Sumanapala.)

(From OE-Core rev: ff11ca44fec8e4b2aa523e032bd967e3ab8339a8)

(From OE-Core rev: 5637d1555b51569cdd7202ee47a0b913a0b429cb)

Signed-off-by: Armin Kuster <akuster@mvista.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Armin Kuster
19bee74728 tzcode-native: update to 2016h
Changes to code

zic no longer mishandles relativizing file names when creating
symbolic links like /etc/localtime, when these symbolic links
are outside the usual directory hierarchy.  This fixes a bug
introduced in 2016g.  (Problem reported by Andreas Stieger.)

(From OE-Core rev: 9c5de646e01a83219be74e99dcf7c1e56ba38b53)

(From OE-Core rev: 9288b6e699abbf5b314029b0db9230ca159b335a)

Signed-off-by: Armin Kuster <akuster@mvista.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Robert P. J. Day
849863fdaf testsdk.bbclass: Clean up comments, clarify image choices.
Make it clear that SDK testing can use any valid image.

(From OE-Core rev: d190c69347921a626665a53469dcf99b3c86994b)

(From OE-Core rev: 7c16202e8c532f4d6ae78ac4bd324f7d975e8a76)

Signed-off-by: Robert P. J. Day <rpjday@crashcourse.ca>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Olaf Mandel
ac8981c01d texi2html: Allow compiling out-of-source
Compiling texi2html 5.0 out-of-source with USE_NLS set to no failed
because it tried to copy from srcdir without using that variable.
Fix this issue and add a reference to the upstream commit.

(From OE-Core rev: 28a37020f50e513b247015b1b0a784c99d41aae3)

(From OE-Core rev: f31ec69379a752e18321ce600a09db9de48fc263)

Signed-off-by: Olaf Mandel <o.mandel@menlosystems.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
3081194a9f valgrind: update to 3.12.0
Remove backported gcc5-port.patch
Remove 11_mips-link-tool.patch as there is nothing in the target file
(or the entire source tree) that resembles anything contained in the patch.

(From OE-Core rev: 221093e850fbc3c154e9069f1958384b59ba3f70)

(From OE-Core rev: 7178febeb04f9b7326554f6b57ed50345fd95126)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
b6335e4251 libarchive: update to 3.2.2
(From OE-Core rev: 14fc66856a59e44d6861ed4ef88909908e597615)

(From OE-Core rev: 9fde7e21d5f61553c371124380982ecd6402ccb9)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
274d77860f libwnck3: remove the recipe
Nothing requires it in oe-core now, so it will be re-added to meta-openembedded.

(From OE-Core rev: 5741419426c6f8255d55560e3a4721fa4c68a179)

(From OE-Core rev: 129281e8557ec8d29ecf863675884713a3050f4b)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
8d2e24810e epiphany: remove unnecessary libwnck3 dependency
libwnck3 dependency was removed upstream

(From OE-Core rev: 0af26d519fd282d0b270939a75ce33eba715669b)

(From OE-Core rev: fb5c4f181176710a4cfb3c875b5edb4e5aa5df73)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
a368478133 rt-tests: fix the recipe version to match upstream
Upstream had a 2.0 tag for a while, then removed it and added a 1.1 tag :-/
Let's make it match to avoid confusion. There's only one new commit
added, which adds a missing manpage.

Also, update the outdated version comment in rt-tests.inc

(From OE-Core rev: 799a7b74f1219040fe2d43dcdcd145600a9fecbd)

(From OE-Core rev: 5a577f1aa4891646075a559fc94e52cfe34b96c9)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
77bc68c7ac webkitgtk: remove lib_package inherit as executables are now installed in libexecdir
(From OE-Core rev: 60751d66118103712f7670412051234cec41e439)

(From OE-Core rev: dd46a43b9ebc6b3183e5ad154c1736330e93e04e)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
4708f7af51 gnome-desktop3: fix dependencies
libxrandr dependency has been removed upstream

Udev dependecy has been added upstream:

    commit b8cbfbe06475703f333367976eae9477f229891a

    pnp-ids: Use udev's hwdb to query PNP IDs

(From OE-Core rev: 5f939fbf229e3c05d6b726f481a0e862ad5a5ceb)

(From OE-Core rev: 623f9eb815ae0a53f96222947b566c4e6d74ab97)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Alexander Kanavin
17a550b9de lttng-tools: do not install shared libraries in ptest package
This was creating a race in runtime library dependency resolution
where sometimes the library was assumed to be provided by the ptest
package.

(From OE-Core rev: c4a10c0b4bc14f4bac06deed8ecb64d0303f4029)

(From OE-Core rev: 10e32463236df05458af7fb7d1ef388f380ab10c)

Signed-off-by: Alexander Kanavin <alexander.kanavin@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Ross Burton
30cdca66c5 shadow: add nologin.8 to alternatives
This manpage is also shipped in util-linux-doc as an alternative, so it needs to
be managed as an alternative here too.

(From OE-Core rev: 0c1e8e0939b39dcf6ea753b41da5ec9bc6ebb82a)

(From OE-Core rev: 4a916484adbf7ae38338279b83f8a64c2cee4f3e)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Ross Burton
54e8fa5060 util-linux: add su.1 to update-alternatives
The su binary is handled by alternatives but the man page wasn't, so
installing both util-linux-doc and shadow-doc produces errors.

Also use d.expand() to neaten the code.

(From OE-Core rev: 70a161ee88d3d54fec6d59039c181b43f1857dc3)

(From OE-Core rev: bec07530536c36b2ab2a7818a9ffc475faba27ac)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Mike Looijmans
9600da51e4 busybox/mdev.conf: Ignore eMMC RPMB and boot block devices
eMMC devices may report block devices like "mmcblk0rpmb" and
"mmcblk0boot0". These are not actually block devices and any
read/write operation on them will fail. To prevent spamming error
messages attempting to mount them, just ignore these devices.

(From OE-Core rev: 9f4a85eb929f67420d9689d7dddadd120ed49843)

(From OE-Core rev: 50d97edaeb18a4c6374101d222410a3b0f344bf2)

Signed-off-by: Mike Looijmans <mike.looijmans@topic.nl>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Samuli Piippo
ee6ff5ce83 package_manager.py: correctly remove all dependent packages
Do not use --force-depends when trying to remove all dependent packages,
as it removes only the selected package and not the dependent packages.

(From OE-Core rev: a82e8725902086dab785a0b14305927dae1e4e8d)

(From OE-Core rev: 0666c66b2719f59e556c12d5875dea696006ed0b)

Signed-off-by: Samuli Piippo <samuli.piippo@qt.io>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Robert Yang
7a308a7919 insane.bbclass:buildpaths: open() file with 'rb'
open() is default to 'rt' which may cause decoding errors when open
binary file:
$ bitbake xcursor-transparent-theme
[snip]
Exception: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfd in position 18: invalid start byte
[snip]

(From OE-Core rev: ddbab61f47efd9b4fde38ef8f0f3482c78abe37c)

(From OE-Core rev: 8364558a2904d21c9b31d29bfb8f2d9cbeac8659)

Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:57 +00:00
Paul Eggleton
6a1ef8a965 classes/nativesdk: set SDK_OLDEST_KERNEL appropriately
SDK_OLDEST_KERNEL currently only controls the check on SDK installation,
however as with OLDEST_KERNEL it should be controlling the OLDEST_KERNEL
value for building glibc used in the SDK. Thus, set it in
nativesdk.bbclass. This means we need to move the default to
bitbake.conf so that it can be seen in both places.

Also set a more reasonable default for SDK_OLDEST_KERNEL for x86/x86-64 as
glibc 2.24 still supports back to 2.6.32 there and there are still
people wanting to build SDKs that will install on older distros (e.g.
CentOS 6). However it's not possible to set this with overrides since
there aren't any for the SDK_ARCH, however we can instead set the variable
from conf files in conf/machine-sdk especially as there is now a soft
default for SDKMACHINE.

Fixes [YOCTO #10561].

(From OE-Core rev: 42d5781e31c5bf76b5b7e27abed4f6f3fd65bf40)

(From OE-Core rev: e02aa8e8b62eae0f83beca850466408dd060b248)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Paul Eggleton
95a10d1dfc classes/populate_sdk_base: fix usage of & character in SDK_TITLE
If you used an & character in SDK_TITLE (possibly indirectly from
DISTRO_NAME) then sed interpreted this as a directive to paste in the
replaced string (@SDK_TITLE@ in this case). Escape any & characters in
SDK_TITLE to avoid that.

(From OE-Core rev: acb85689c13cfdac21435509001048af5c3a7e99)

(From OE-Core rev: bbad3402d431ac178cabdc00fcaf37b3a1a6bfd6)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Yi Zhao
914e89709c tiff: Security fix CVE-2016-3622
CVE-2016-3622 libtiff: The fpAcc function in tif_predict.c in the
tiff2rgba tool in LibTIFF 4.0.6 and earlier allows remote attackers to
cause a denial of service (divide-by-zero error) via a crafted TIFF
image.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3622
http://www.openwall.com/lists/oss-security/2016/04/07/4

Patch from:
92d966a5fc

(From OE-Core rev: 0af0466f0381a72b560f4f2852e1d19be7b6a7fb)

(From OE-Core rev: 928eadf8442cf87fb2d4159602bd732336d74bb7)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Yi Zhao
f33e739fc2 tiff: Security fix CVE-2016-3623
CVE-2016-3623 libtiff: The rgb2ycbcr tool in LibTIFF 4.0.6 and earlier
allows remote attackers to cause a denial of service (divide-by-zero) by
setting the (1) v or (2) h parameter to 0.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3623
http://bugzilla.maptools.org/show_bug.cgi?id=2569

Patch from:
bd024f0701

(From OE-Core rev: d66824eee47b7513b919ea04bdf41dc48a9d85e9)

(From OE-Core rev: f0e77ffa6bbc3adc61a2abd5dbc9228e830c055d)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Yi Zhao
719a8dcd0d tiff: Security fix CVE-2016-3991
CVE-2016-3991 libtiff: Heap-based buffer overflow in the loadImage
function in the tiffcrop tool in LibTIFF 4.0.6 and earlier allows remote
attackers to cause a denial of service (out-of-bounds write) or execute
arbitrary code via a crafted TIFF image with zero tiles.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3991
http://bugzilla.maptools.org/show_bug.cgi?id=2543

Patch from:
e596d4e27c

(From OE-Core rev: d31267438a654ecb396aefced201f52164171055)

(From OE-Core rev: cf58711f12425fc1c29ed1e3bf3919b3452aa2b2)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Yi Zhao
d94c22d4e4 tiff: Security fix CVE-2016-3990
CVE-2016-3990 libtiff: Heap-based buffer overflow in the
horizontalDifference8 function in tif_pixarlog.c in LibTIFF 4.0.6 and
earlier allows remote attackers to cause a denial of service (crash) or
execute arbitrary code via a crafted TIFF image to tiffcp.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3990
http://bugzilla.maptools.org/show_bug.cgi?id=2544

Patch from:
6a4dbb07cc

(From OE-Core rev: c6492563037bcdf7f9cc50c8639f7b6ace261e62)

(From OE-Core rev: d7165cd738ac181fb29d2425e360f2734b0d1107)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Yi Zhao
ee2a19d38e tiff: Security fix CVE-2016-3945
CVE-2016-3945 libtiff: Multiple integer overflows in the (1)
cvt_by_strip and (2) cvt_by_tile functions in the tiff2rgba tool in
LibTIFF 4.0.6 and earlier, when -b mode is enabled, allow remote
attackers to cause a denial of service (crash) or execute arbitrary code
via a crafted TIFF image, which triggers an out-of-bounds write.

External References:
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-3945
http://bugzilla.maptools.org/show_bug.cgi?id=2545

Patch from:
7c39352ccd

(From OE-Core rev: 04b9405c7e980d7655c2fd601aeeae89c0d83131)

(From OE-Core rev: 3a4d2618c50aed282af335ef213c5bc0c9f0534e)

Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Chen Qi
57bcb0b509 systemd: CVE-2016-7795
The manager_invoke_notify_message function in systemd 231 and earlier allows
local users to cause a denial of service (assertion failure and PID 1 hang)
via a zero-length message received over a notify socket.

The patch is a backport from the latest git repo.

Please see the link below for more information.
https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-7795

(From OE-Core rev: 543570cafa8d7f595b489d03d05f0aa4478f8539)

(From OE-Core rev: df3f4785fc69d3ddbd30ccd954aad3d3618c5916)

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Robert Yang
698bbcad68 oe/copy_buildsystem.py: dereference symlink
When there is a relative symlink in the layer, for example:
symA -> ../out/of/layer/file

symA will be invalid fater copied, it would be invalid from build time
if it points to a relative path, and would be invalid after extracted
the sdk if it points to a absolute py. Dereference symlink when copy
will fix the problem.

Use tar rather than shutil.copytree() to copy is because:
1) shutil.copytree(symlinks=Fasle) has bugs when dereference symlinks:
   https://bugs.python.org/issue21697
   And Ubunutu 1404 doesn't upgrade python3 to fix the problem.

2) shutil.copytree(symlinks=False) raises errors when there is a invalid
   symlink, and tar just prints a warning, tar is preferred here since
   the real world is unpredicatable

3) tar is faster than shutil.copytree() as said by oe.path.copytree()

So use tar to copy.

(From OE-Core rev: f4d70bb0882eec4fb46cd942f2796fad57c72982)

(From OE-Core rev: 51d3cab8aab593481be16cadaca6fcddbb64bc52)

Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Dmitry Rozhkov
25fa4e9e8f openssl: rehash actual mozilla certificates inside rootfs
The c_rehash utility is supposed to be run in the folder /etc/ssl/certs
of a rootfs where the package ca-certificates puts symlinks to
various CA certificates stored in /usr/share/ca-certificates/mozilla/.
These symlinks are absolute. This means that when c_rehash is run
at rootfs creation time it can't hash the actual files since they
actually reside in the build host's directory
$SYSROOT/usr/share/ca-certificates/mozilla/.

This problem doesn't reproduce when building on Debian or Ubuntu
hosts though, because these OSs have the certificates installed
in the same /usr/share/ca-certificates/mozilla/ folder.
Images built in other distros, e.g. Fedora, have problems with
connecting to https servers when using e.g. python's http lib.

The patch fixes c_rehash to check if it runs on a build host
by testing $SYSROOT and to translate the paths to certificates
accordingly.

(From OE-Core rev: 5199b990edf4d9784c19137d0ce9ef141cd85e46)

(From OE-Core rev: 9ab0cba49d9ab67aacfcfb47689f4a77a72a0866)

Signed-off-by: Dmitry Rozhkov <dmitry.rozhkov@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
George McCollister
3d471b811d uboot-sign: fix do_concat_dtb for .img, .rom
Now that out of tree building is enabled, ${B} must be used instead of
${S} as the path for UBOOT_BINARY.

(From OE-Core rev: 1fe17c52e4d7ce1b9d69aaa2cd9d4b351a4b2603)

(From OE-Core rev: 87705ab8f7224dbc1f397f9c388260a6370a06d9)

Signed-off-by: George McCollister <george.mccollister@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Chen Qi
8b84b31dc2 rpm: fix file location of rpm2cpio.real
rpm2cpio is in ${PN}-common, but rpm2cpio.real is in ${PN}. This seperation
is really weird. Put them both in ${PN}-common.

(From OE-Core rev: 8a0af7e4ae8ba8ce0c7fd2a9f6ab7cc070f47af0)

(From OE-Core rev: 0f87812a515ae349885929558fbfb315f4a10ec7)

Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
André Draszik
2e6624293c boost: disable 'wave' in MIPS16e mode
This doesn't compile, see
  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77757#c2

(From OE-Core rev: 59f77d48528498f12cc9d1ba641a9c7ff50ba03a)

(From OE-Core rev: eaed926c023d1e25c29dcfc078c37461e29895b9)

Signed-off-by: André Draszik <adraszik@tycoint.com>
Acked-by: Sylvain Lemieux <slemieux@tycoint.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Ross Burton
8c69cdacea slang: clean up options and dependencies
The AC_PATH_XTRA check for X11 headers is never actually used, so patch that out
and remove the options in EXTRA_OECONF.

Move pcre/png/zlib toggles to PACKAGECONFIG, retaining the behaviour that only
PCRE is enabled by default.

Add missing libiconv dependency.

(From OE-Core rev: 3587053646c34002fa18b87834516ce27fbd0788)

(From OE-Core rev: 200cc00b048dbef11b01c6402d6525559de76306)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Ross Burton
b814b6df0b slang: add PREMIRRORS to handle upstream moving tarballs
The slang maintainer only puts the current release at
jedsoft.org/releases/slang/slang-1.2.3.tar.bz2, all previous releases are moved
into /releases/slang/old/.

As this breaks the fetch the moment a new version is released, use PREMIRRORS to
also look in the /old/ directory.

(From OE-Core rev: 50d49766ab76b67e312f6a1d91977a40d1020919)

(From OE-Core rev: f2783109ac7939eba722dc2f863661ade03e4a8a)

Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Paul Eggleton
26e8ebc511 classes/license: fix handling of symlinks pointed to in LIC_FILES_CHKSUM
If you set LIC_FILES_CHKSUM to point to a relative symlink then you'll
get "Could not copy license file" warnings in copy_license_files() since
the symlink won't be valid after it's copied. If the source is a symlink
then we need to dereference it first.

I encountered this when I used recipetool on the sources for capnproto,
where the c++ directory contains a LICENSE.txt symlink to the LICENSE
file in the parent directory, and this symlink ends up being pointed to
in LIC_FILES_CHKSUM.

(From OE-Core rev: c4d3b1e9c37b920444e53d3231552da18d101882)

(From OE-Core rev: 650ddf1d8b687845099a8ac463c3a550a7965095)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Lukasz Nowak
874ccd1bb3 connman: fix bad file descriptor initialisation
Import a patch from upstream, which fixes a connman daemon freeze
under certain conditions (multiple active interfaces, no r/w storage).

(From OE-Core rev: bba18cdce6fb6c5ff2f7161198d46607a72747d6)

(From OE-Core rev: 87d6ccd8c7775b1d3e2571b6e17091538a8bd6c8)

Signed-off-by: Lukasz Nowak <lnowak@tycoint.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Juro Bystricky
a628a17a44 build-appliance-image: Fix incorrect PATH
When modifying the PATH variable in .bashrc, double quote characters
were used, resulting in expanding the variable $PATH with the value of
PATH of the system building the Build Appliance.

The original intent was to enter an un-expanded (literal) $PATH.
In order to that, one must use single quotes instead of double quotes.

[YOCTO#10434] [YOCTO#10504]

(From OE-Core rev: 6238faf901956e2a350315a66ca1ce557deaa513)

(From OE-Core rev: ac2b0413526df46cfdcae2d3f9add1a29fe3c2b5)

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Markus Lehtonen
4d30681e8b python: fix python-tests rdepends
test.regrtest depends on most of python modules so require all of them.

[YOCTO #10522]

(From OE-Core rev: a8dc4bc039d1c01a78fdc1f727cbfc6f2feffe93)

(From OE-Core rev: 545a2d41f57232d58d19feb3fb0375be5553e47d)

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
Khem Raj
4722bfbda9 binutils-2.27: Fix linker segfaults when linking binary files
Fixes segfaults when doing partial linking and generaring binary objects

/tmp/binu/ld/ld-new -r -b binary -o etc_certs_ui_ca_pem.o etc_certs_ui_ca_pem

0  elf32_arm_count_additional_relocs (sec=0x79bf40) at /mnt/a/work/oe/binutils-gdb/bfd/elf32-arm.c:18210
1  0x000000000047635a in bfd_elf_final_link (abfd=abfd@entry=0x783250, info=info@entry=0x748400 <link_info>) at /mnt/a/work/oe/binutils-gdb/bfd/elflink.c:11224
2  0x000000000044df7b in elf32_arm_final_link (abfd=0x783250, info=0x748400 <link_info>) at /mnt/a/work/oe/binutils-gdb/bfd/elf32-arm.c:12131
3  0x0000000000418917 in ldwrite () at /mnt/a/work/oe/binutils-gdb/ld/ldwrite.c:577
4  0x000000000040365f in main (argc=<optimized out>, argv=<optimized out>) at /mnt/a/work/oe/binutils-gdb/ld/ldmain.c:433

gold works ok. The patch is already applied in master binutils

(From OE-Core rev: 00d1913520f1572fa7def865e57852c7f25b0ec4)

(From OE-Core rev: 2b1a571899eec018d6f44876b743e06835ed761d)

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-16 10:37:56 +00:00
brian avery
6c9f6b5f70 bitbake: toaster: buildinfohelper Handle regex paths
We were presuming that all the layer dependency information was of the
form "^/path/to/layer" to we were just stripping the leading "^" off of
the layer information when we were matching the layer priorities to the
toaster database.  This patch splits out the priorities layer match which
gets a  regex from the task/recipe match which is gets a path.

(Bitbake rev: 82775c80d169266cc18ca2b2065a05c79dc6fbfc)

Signed-off-by: brian avery <brian.avery@intel.com>
Signed-off-by: Michael Wood <michael.g.wood@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-11-03 17:41:15 +00:00
Richard Purdie
dc8508f609 build-applance-image: Fix to use the release branch for morty
(From OE-Core rev: 2a59d0fa7bda78927435603e3049ce373cf6a198)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 11:11:10 +01:00
Richard Purdie
bf5dd36042 build-appliance-image: Update to morty head revision
(From OE-Core rev: 742e6d462948cdc89e5c538c9d834ff4fb42352e)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:34:02 +01:00
Kevin Hao
746c681be4 meta-yocto-bsp: linux-yocto: bump to the latest stable version for non-x86 BSPs
Built and boot test for all these boards on 4.1, 4.4 and 4.8 kernels.

(From meta-yocto rev: d4627701a3a5d8c82f49747c41c5b3226da56d07)

Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:31:59 +01:00
Alejandro Hernandez
73aa36e3ee linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.4
Upgrades to Linux 4.4.26

(From meta-yocto rev: 96275ed6faffd11b4ca2e958381f3b02122f1eeb)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:31:59 +01:00
Alejandro Hernandez
cddb7f10b8 linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.1
(From meta-yocto rev: 16ef41db64dffb57a8a863631e20fde2521f1880)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:31:59 +01:00
Alejandro Hernandez
399903724b linux-yocto: Update genericx86* SRCREVs for linux-yocto 4.8
Upgrades to Linux 4.8.3

(From meta-yocto rev: eef04c03f794a7776129118e99feb94165e8fd5e)

Signed-off-by: Alejandro Hernandez <alejandro.hernandez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:31:59 +01:00
Bruce Ashfield
e09163a08b linux-yocto/4.8: sync preempt-rt with upstream project
The initial 4.8 -rt feature was directly from Paul Gortmaker, and
now the 'upstream' -rt has done a release on the same kernel
version.

Paul has sync'd the initial effort with the upstream work, and we
now have a consolidated standard/preempt-rt/*

Along with the rsync'd content, Paul has fixed -rt boot on 32 bit
x86.

(From OE-Core rev: 1270050079feeefc38744fdbfe23b16aa1b632a3)

Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-26 09:31:59 +01:00
Paul Eggleton
2c0efd2f33 devtool: runqemu: work around runqemu script path assumption
The new runqemu script assumes that if OECORE_NATIVE_SYSROOT is set then
it shouldn't try to run bitbake to find out the values of various
variables such as DEPLOY_DIR_IMAGE; this assumption is incorrect for the
extensible SDK. To work around this, clear OECORE_NATIVE_SYSROOT in the
environment when running runqemu.

Fixes [YOCTO #10447].

(From OE-Core rev: abff69a48bf3076ce8e21356accdc8d85d2c8dbf)

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 22:40:13 +01:00
Saul Wold
fb1df184b9 image_types: Use softer setting of WKS_FILE
This will allow for more flexibility and overrides in BSP
layers.

(From OE-Core rev: 1886ab2f1dc1e3b5758a85604998e8deb9198f5e)

Signed-off-by: Saul Wold <sgw@linux.intel.com>
Signed-off-by: Ross Burton <ross.burton@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:59:04 +01:00
Scott Rifenbark
e127d017e1 ref-manual: Removed host package requirements for SDK
These requirements were in place for the ADT, which is gone now.
I have removed the four supported host lists for packages to
support the SDK.

(From yocto-docs rev: e0f36333b3a0e5f3503f6ac48b87c3ae8c23afe3)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
0915ee7dc3 ref-manual: Applied minor corrections to 2.2 migration section.
Moved a couple notes around and changed some wordings...
nothing major.

(From yocto-docs rev: 518d368c4c981df5ddde6681859906c9eb16ff62)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
7c3cdf8a17 yocto-project-qs: Created two sub-sections for the "Build" section.
Fixes [YOCTO #10462]

The section that shows how to build images had two examples all
within the same section.  It was suggested to place these examples
in their own sub-sections.  Good suggestion.  I broke them out into
sub-sections titled appropriately.

(From yocto-docs rev: b97918820cfa12a2d5dfbccd6c0ce22b16d65206)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
9ae4ab56e7 yocto-project-qs: Fixed the example to use 'dd' instead of 'mkefidisk.sh'
Fixes [YOCTO #10451]

The example that writes the image to bootable media did not seem
to work when using 'mkefidisk.sh'.  It does work using 'dd'.  I changed
the procedure to use 'dd'.

(From yocto-docs rev: e3f90869291f619db1d830b127ade66986eba886)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
e40a8d739a ref-manual: Added BBMULTICONFIG glossary description.
(From yocto-docs rev: a37069875e661ee07edf17275441c29d84363479)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
5e0d6341ab dev-manual: Added section for multi-configuration support
I added a new section in the "Common Tasks" chapter to support
the fact that BB can now build for multi-configurations.

(From yocto-docs rev: 0bf464908200d6c40c35fbf753712a8b0201dd88)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
Scott Rifenbark
41e74881b0 ref-manual: Updated 2.2 migration for runqemu porting to python
Indicated that the configuration file is not mandatory.  Also,
documented the supported qemu* machines should you run the
script without a configuration file.

(From yocto-docs rev: c01e8ff8e3233e56a220be042616d5810f181a58)

Signed-off-by: Scott Rifenbark <srifenbark@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
2016-10-25 17:56:27 +01:00
4595 changed files with 219369 additions and 181932 deletions

10
.gitignore vendored
View File

@@ -18,13 +18,9 @@ hob-image-*.bb
!meta-yocto
!meta-yocto-bsp
!meta-yocto-imported
/documentation/*/eclipse/
/documentation/*/*.html
/documentation/*/*.pdf
/documentation/*/*.tgz
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.html
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.pdf
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.tgz
documentation/user-manual/user-manual.html
documentation/user-manual/user-manual.pdf
documentation/user-manual/user-manual.tgz
pull-*/
bitbake/lib/toaster/contrib/tts/backlog.txt
bitbake/lib/toaster/contrib/tts/log/*

58
README Normal file
View File

@@ -0,0 +1,58 @@
Poky
====
Poky is an integration of various components to form a complete prepackaged
build system and development environment. It features support for building
customised embedded device style images. There are reference demo images
featuring a X11/Matchbox/GTK themed UI called Sato. The system supports
cross-architecture application development using QEMU emulation and a
standalone toolchain and SDK with IDE integration.
Additional information on the specifics of hardware that Poky supports
is available in README.hardware. Further hardware support can easily be added
in the form of layers which extend the systems capabilities in a modular way.
As an integration layer Poky consists of several upstream projects such as
BitBake, OpenEmbedded-Core, Yocto documentation and various sources of information
e.g. for the hardware support. Poky is in turn a component of the Yocto Project.
The Yocto Project has extensive documentation about the system including a
reference manual which can be found at:
http://yoctoproject.org/documentation
OpenEmbedded-Core is a layer containing the core metadata for current versions
of OpenEmbedded. It is distro-less (can build a functional image with
DISTRO = "nodistro") and contains only emulated machine support.
For information about OpenEmbedded, see the OpenEmbedded website:
http://www.openembedded.org/
Where to Send Patches
=====================
As Poky is an integration repository (built using a tool called combo-layer),
patches against the various components should be sent to their respective
upstreams:
bitbake:
Git repository: http://git.openembedded.org/bitbake/
Mailing list: bitbake-devel@lists.openembedded.org
documentation:
Git repository: http://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/
Mailing list: yocto@yoctoproject.org
meta-poky, meta-yocto-bsp:
Git repository: http://git.yoctoproject.org/cgit/cgit.cgi/meta-yocto(-bsp)
Mailing list: poky@yoctoproject.org
Everything else should be sent to the OpenEmbedded Core mailing list. If in
doubt, check the oe-core git repository for the content you intend to modify.
Before sending, be sure the patches apply cleanly to the current oe-core git
repository.
Git repository: http://git.openembedded.org/openembedded-core/
Mailing list: openembedded-core@lists.openembedded.org
Note: The scripts directory should be treated with extra care as it is a mix of
oe-core and poky-specific files.

View File

@@ -1,26 +0,0 @@
OE-Core aims to be able to provide basic LSB compatible images. There
are some challenges for OE as LSB isn't always 100% relevant to its
target embedded and IoT audiences.
One challenge is that the LSB spec is no longer being actively
developed [https://github.com/LinuxStandardBase/lsb] and has
components which are end of life or significantly dated. OE
therefore provides compatibility with the following caveats:
* Qt4 is provided by the separate meta-qt4 layer. Its noted that Qt4
is end of life and this isn't something the core project regularly
tests any longer. Users are recommended to group together to support
maintenance of that layer. [http://git.yoctoproject.org/cgit/cgit.cgi/meta-qt4/]
* mailx has been dropped since its no longer being developed upstream
and there are better, more modern replacements such as s-nail
(http://sdaoden.eu/code.html) or mailutils (http://mailutils.org/).
* A few perl modules that were required by LSB 4.x aren't provided:
libclass-isa, libenv, libdumpvalue, libfile-checktree,
libi18n-collate, libpod-plainer.
* libpng 1.2 isn't provided; oe-core includes the latest release of libpng
instead.
* pax (POSIX standard archive) tool is not provided.

View File

@@ -1 +0,0 @@
meta-yocto-bsp/README.hardware

360
README.hardware Normal file
View File

@@ -0,0 +1,360 @@
Poky Hardware README
====================
This file gives details about using Poky with the reference machines
supported out of the box. A full list of supported reference target machines
can be found by looking in the following directories:
meta/conf/machine/
meta-yocto-bsp/conf/machine/
If you are in doubt about using Poky/OpenEmbedded with your hardware, consult
the documentation for your board/device.
Support for additional devices is normally added by creating BSP layers - for
more information please see the Yocto Board Support Package (BSP) Developer's
Guide - documentation source is in documentation/bspguide or download the PDF
from:
http://yoctoproject.org/documentation
Support for physical reference hardware has now been split out into a
meta-yocto-bsp layer which can be removed separately from other layers if not
needed.
QEMU Emulation Targets
======================
To simplify development, the build system supports building images to
work with the QEMU emulator in system emulation mode. Several architectures
are currently supported:
* ARM (qemuarm)
* x86 (qemux86)
* x86-64 (qemux86-64)
* PowerPC (qemuppc)
* MIPS (qemumips)
Use of the QEMU images is covered in the Yocto Project Reference Manual.
The appropriate MACHINE variable value corresponding to the target is given
in brackets.
Hardware Reference Boards
=========================
The following boards are supported by the meta-yocto-bsp layer:
* Texas Instruments Beaglebone (beaglebone)
* Freescale MPC8315E-RDB (mpc8315e-rdb)
For more information see the board's section below. The appropriate MACHINE
variable value corresponding to the board is given in brackets.
Reference Board Maintenance
===========================
Send pull requests, patches, comments or questions about meta-yocto-bsps to poky@yoctoproject.org
Maintainers: Kevin Hao <kexin.hao@windriver.com>
Bruce Ashfield <bruce.ashfield@windriver.com>
Consumer Devices
================
The following consumer devices are supported by the meta-yocto-bsp layer:
* Intel x86 based PCs and devices (genericx86)
* Ubiquiti Networks EdgeRouter Lite (edgerouter)
For more information see the device's section below. The appropriate MACHINE
variable value corresponding to the device is given in brackets.
Specific Hardware Documentation
===============================
Intel x86 based PCs and devices (genericx86*)
=============================================
The genericx86 and genericx86-64 MACHINE are tested on the following platforms:
Intel Xeon/Core i-Series:
+ Intel NUC5 Series - ix-52xx Series SOC (Broadwell)
+ Intel NUC6 Series - ix-62xx Series SOC (Skylake)
+ Intel Shumway Xeon Server
Intel Atom platforms:
+ MinnowBoard MAX - E3825 SOC (Bay Trail)
+ MinnowBoard MAX - Turbot (ADI Engineering) - E3826 SOC (Bay Trail)
- These boards can be either 32bot or 64bit modes depending on firmware
- See minnowboard.org for details
+ Intel Braswell SOC
and is likely to work on many unlisted Atom/Core/Xeon based devices. The MACHINE
type supports ethernet, wifi, sound, and Intel/vesa graphics by default in
addition to common PC input devices, busses, and so on.
Depending on the device, it can boot from a traditional hard-disk, a USB device,
or over the network. Writing generated images to physical media is
straightforward with a caveat for USB devices. The following examples assume the
target boot device is /dev/sdb, be sure to verify this and use the correct
device as the following commands are run as root and are not reversable.
USB Device:
1. Build a live image. This image type consists of a simple filesystem
without a partition table, which is suitable for USB keys, and with the
default setup for the genericx86 machine, this image type is built
automatically for any image you build. For example:
$ bitbake core-image-minimal
2. Use the "dd" utility to write the image to the raw block device. For
example:
# dd if=core-image-minimal-genericx86.hddimg of=/dev/sdb
If the device fails to boot with "Boot error" displayed, or apparently
stops just after the SYSLINUX version banner, it is likely the BIOS cannot
understand the physical layout of the disk (or rather it expects a
particular layout and cannot handle anything else). There are two possible
solutions to this problem:
1. Change the BIOS USB Device setting to HDD mode. The label will vary by
device, but the idea is to force BIOS to read the Cylinder/Head/Sector
geometry from the device.
2. Use a ".wic" image with an EFI partition
a) With a default grub-efi bootloader:
# dd if=core-image-minimal-genericx86-64.wic of=/dev/sdb
b) Use systemd-boot instead
- Build an image with EFI_PROVIDER="systemd-boot" then use the above
dd command to write the image to a USB stick.
Texas Instruments Beaglebone (beaglebone)
=========================================
The Beaglebone is an ARM Cortex-A8 development board with USB, Ethernet, 2D/3D
accelerated graphics, audio, serial, JTAG, and SD/MMC. The Black adds a faster
CPU, more RAM, eMMC flash and a micro HDMI port. The beaglebone MACHINE is
tested on the following platforms:
o Beaglebone Black A6
o Beaglebone A6 (the original "White" model)
The Beaglebone Black has eMMC, while the White does not. Pressing the USER/BOOT
button when powering on will temporarily change the boot order. But for the sake
of simplicity, these instructions assume you have erased the eMMC on the Black,
so its boot behavior matches that of the White and boots off of SD card. To do
this, issue the following commands from the u-boot prompt:
# mmc dev 1
# mmc erase 0 512
To further tailor these instructions for your board, please refer to the
documentation at http://www.beagleboard.org/bone and http://www.beagleboard.org/black
From a Linux system with access to the image files perform the following steps:
1. Build an image. For example:
$ bitbake core-image-minimal
2. Use the "dd" utility to write the image to the SD card. For example:
# dd core-image-minimal-beaglebone.wic of=/dev/sdb
3. Insert the SD card into the Beaglebone and boot the board.
Freescale MPC8315E-RDB (mpc8315e-rdb)
=====================================
The MPC8315 PowerPC reference platform (MPC8315E-RDB) is aimed at hardware and
software development of network attached storage (NAS) and digital media server
applications. The MPC8315E-RDB features the PowerQUICC II Pro processor, which
includes a built-in security accelerator.
(Note: you may find it easier to order MPC8315E-RDBA; this appears to be the
same board in an enclosure with accessories. In any case it is fully
compatible with the instructions given here.)
Setup instructions
------------------
You will need the following:
* NFS root setup on your workstation
* TFTP server installed on your workstation
* Straight-thru 9-conductor serial cable (DB9, M/F) connected from your
PC to UART1
* Ethernet connected to the first ethernet port on the board
--- Preparation ---
Note: if you have altered your board's ethernet MAC address(es) from the
defaults, or you need to do so because you want multiple boards on the same
network, then you will need to change the values in the dts file (patch
linux/arch/powerpc/boot/dts/mpc8315erdb.dts within the kernel source). If
you have left them at the factory default then you shouldn't need to do
anything here.
--- Booting from NFS root ---
Load the kernel and dtb (device tree blob), and boot the system as follows:
1. Get the kernel (uImage-mpc8315e-rdb.bin) and dtb (uImage-mpc8315e-rdb.dtb)
files from the tmp/deploy directory, and make them available on your TFTP
server.
2. Connect the board's first serial port to your workstation and then start up
your favourite serial terminal so that you will be able to interact with
the serial console. If you don't have a favourite, picocom is suggested:
$ picocom /dev/ttyUSB0 -b 115200
3. Power up or reset the board and press a key on the terminal when prompted
to get to the U-Boot command line
4. Set up the environment in U-Boot:
=> setenv ipaddr <board ip>
=> setenv serverip <tftp server ip>
=> setenv bootargs root=/dev/nfs rw nfsroot=<nfsroot ip>:<rootfs path> ip=<board ip>:<server ip>:<gateway ip>:255.255.255.0:mpc8315e:eth0:off console=ttyS0,115200
5. Download the kernel and dtb, and boot:
=> tftp 1000000 uImage-mpc8315e-rdb.bin
=> tftp 2000000 uImage-mpc8315e-rdb.dtb
=> bootm 1000000 - 2000000
--- Booting from JFFS2 root ---
1. First boot the board with NFS root.
2. Erase the MTD partition which will be used as root:
$ flash_eraseall /dev/mtd3
3. Copy the JFFS2 image to the MTD partition:
$ flashcp core-image-minimal-mpc8315e-rdb.jffs2 /dev/mtd3
4. Then reboot the board and set up the environment in U-Boot:
=> setenv bootargs root=/dev/mtdblock3 rootfstype=jffs2 console=ttyS0,115200
Ubiquiti Networks EdgeRouter Lite (edgerouter)
==============================================
The EdgeRouter Lite is part of the EdgeMax series. It is a MIPS64 router
(based on the Cavium Octeon processor) with 512MB of RAM, which uses an
internal USB pendrive for storage.
Setup instructions
------------------
You will need the following:
* RJ45 -> serial ("rollover") cable connected from your PC to the CONSOLE
port on the device
* Ethernet connected to the first ethernet port on the board
If using NFS as part of the setup process, you will also need:
* NFS root setup on your workstation
* TFTP server installed on your workstation (if fetching the kernel from
TFTP, see below).
--- Preparation ---
Build an image (e.g. core-image-minimal) using "edgerouter" as the MACHINE.
In the following instruction it is based on core-image-minimal. Another target
may be similiar with it.
--- Booting from NFS root / kernel via TFTP ---
Load the kernel, and boot the system as follows:
1. Get the kernel (vmlinux) file from the tmp/deploy/images/edgerouter
directory, and make them available on your TFTP server.
2. Connect the board's first serial port to your workstation and then start up
your favourite serial terminal so that you will be able to interact with
the serial console. If you don't have a favourite, picocom is suggested:
$ picocom /dev/ttyS0 -b 115200
3. Power up or reset the board and press a key on the terminal when prompted
to get to the U-Boot command line
4. Set up the environment in U-Boot:
=> setenv ipaddr <board ip>
=> setenv serverip <tftp server ip>
5. Download the kernel and boot:
=> tftp tftp $loadaddr vmlinux
=> bootoctlinux $loadaddr coremask=0x3 root=/dev/nfs rw nfsroot=<nfsroot ip>:<rootfs path> ip=<board ip>:<server ip>:<gateway ip>:<netmask>:edgerouter:eth0:off mtdparts=phys_mapped_flash:512k(boot0),512k(boot1),64k@3072k(eeprom)
--- Booting from USB disk ---
To boot from the USB disk, you either need to remove it from the edgerouter
box and populate it from another computer, or use a previously booted NFS
image and populate from the edgerouter itself.
Type 1: Use partitioned image
-----------------------------
Steps:
1. Remove the USB disk from the edgerouter and insert it into a computer
that has access to your build artifacts.
2. Flash the image.
# dd core-image-minimal-edgerouter.wic of=/dev/sdb
3. Insert USB disk into the edgerouter and boot it.
Type 2: NFS
-----------
Note: If you place the kernel on the ext3 partition, you must re-create the
ext3 filesystem, since the factory u-boot can only handle 128 byte inodes and
cannot read the partition otherwise.
These boot instructions assume that you have recreated the ext3 filesystem with
128 byte inodes, you have an updated uboot or you are running and image capable
of making the filesystem on the board itself.
1. Boot from NFS root
2. Mount the USB disk partition 2 and then extract the contents of
tmp/deploy/core-image-XXXX.tar.bz2 into it.
Before starting, copy core-image-minimal-xxx.tar.bz2 and vmlinux into
rootfs path on your workstation.
and then,
# mount /dev/sda2 /media/sda2
# tar -xvjpf core-image-minimal-XXX.tar.bz2 -C /media/sda2
# cp vmlinux /media/sda2/boot/vmlinux
# umount /media/sda2
# reboot
3. Reboot the board and press a key on the terminal when prompted to get to the U-Boot
command line:
# reboot
4. Load the kernel and boot:
=> ext2load usb 0:2 $loadaddr boot/vmlinux
=> bootoctlinux $loadaddr coremask=0x3 root=/dev/sda2 rw rootwait mtdparts=phys_mapped_flash:512k(boot0),512k(boot1),64k@3072k(eeprom)

View File

@@ -1 +0,0 @@
meta-poky/README.poky

View File

@@ -1,15 +0,0 @@
QEMU Emulation Targets
======================
To simplify development, the build system supports building images to
work with the QEMU emulator in system emulation mode. Several architectures
are currently supported in 32 and 64 bit variants:
* ARM (qemuarm + qemuarm64)
* x86 (qemux86 + qemux86-64)
* PowerPC (qemuppc only)
* MIPS (qemumips + qemumips64)
Use of the QEMU images is covered in the Yocto Project Reference Manual.
The appropriate MACHINE variable value corresponding to the target is given
in brackets.

View File

@@ -15,5 +15,3 @@ Foundation and individual contributors.
* QUnit is redistributed under the MIT license.
* Font Awesome fonts redistributed under the SIL Open Font License 1.1
* simplediff is distributed under the zlib license.

View File

@@ -1,35 +0,0 @@
Bitbake
=======
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.
For information about Bitbake, see the OpenEmbedded website:
http://www.openembedded.org/
Bitbake plain documentation can be found under the doc directory or its integrated
html version at the Yocto Project website:
http://yoctoproject.org/documentation
Contributing
------------
Please refer to
http://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded
for guidelines on how to submit patches, just note that the latter documentation is intended
for OpenEmbedded (and its core) not bitbake patches (bitbake-devel@lists.openembedded.org)
but in general main guidelines apply. Once the commit(s) have been created, the way to send
the patch is through git-send-email. For example, to send the last commit (HEAD) on current
branch, type:
git send-email -M -1 --to bitbake-devel@lists.openembedded.org
Mailing list:
http://lists.openembedded.org/mailman/listinfo/bitbake-devel
Source code:
http://git.openembedded.org/bitbake/

View File

@@ -36,9 +36,9 @@ from bb import cookerdata
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.")
sys.exit("Please use a locale setting which supports 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.38.0"
__version__ = "1.32.0"
if __name__ == "__main__":
if __version__ != bb.__version__:

View File

@@ -3,7 +3,7 @@
# bitbake-diffsigs
# BitBake task signature data comparison utility
#
# Copyright (C) 2012-2013, 2017 Intel Corporation
# Copyright (C) 2012-2013 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -22,7 +22,7 @@ import os
import sys
import warnings
import fnmatch
import argparse
import optparse
import logging
import pickle
@@ -30,154 +30,109 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), '
import bb.tinfoil
import bb.siggen
import bb.msg
logger = bb.msg.logger_create('bitbake-diffsigs')
def logger_create(name, output=sys.stderr):
logger = logging.getLogger(name)
console = logging.StreamHandler(output)
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
if output.isatty():
format.enable_color()
console.setFormatter(format)
logger.addHandler(console)
logger.setLevel(logging.INFO)
return logger
def find_siginfo(tinfoil, pn, taskname, sigs=None):
result = None
tinfoil.set_event_mask(['bb.event.FindSigInfoResult',
'logging.LogRecord',
'bb.command.CommandCompleted',
'bb.command.CommandFailed'])
ret = tinfoil.run_command('findSigInfo', pn, taskname, sigs)
if ret:
while True:
event = tinfoil.wait_event(1)
if event:
if isinstance(event, bb.command.CommandCompleted):
break
elif isinstance(event, bb.command.CommandFailed):
logger.error(str(event))
sys.exit(2)
elif isinstance(event, bb.event.FindSigInfoResult):
result = event.result
elif isinstance(event, logging.LogRecord):
logger.handle(event)
else:
logger.error('No result returned from findSigInfo command')
sys.exit(2)
return result
logger = logger_create('bitbake-diffsigs')
def find_compare_task(bbhandler, pn, taskname, sig1=None, sig2=None, color=False):
def find_compare_task(bbhandler, pn, taskname):
""" Find the most recent signature files for the specified PN/task and compare them """
def get_hashval(siginfo):
if siginfo.endswith('.siginfo'):
return siginfo.rpartition(':')[2].partition('_')[0]
else:
return siginfo.rpartition('.')[2]
if not hasattr(bb.siggen, 'find_siginfo'):
logger.error('Metadata does not support finding signature data files')
sys.exit(1)
if not taskname.startswith('do_'):
taskname = 'do_%s' % taskname
if sig1 and sig2:
sigfiles = find_siginfo(bbhandler, pn, taskname, [sig1, sig2])
if len(sigfiles) == 0:
logger.error('No sigdata files found matching %s %s matching either %s or %s' % (pn, taskname, sig1, sig2))
sys.exit(1)
elif not sig1 in sigfiles:
logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig1))
sys.exit(1)
elif not sig2 in sigfiles:
logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig2))
sys.exit(1)
latestfiles = [sigfiles[sig1], sigfiles[sig2]]
filedates = bb.siggen.find_siginfo(pn, taskname, None, bbhandler.config_data)
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-3:]
if not latestfiles:
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
sys.exit(1)
elif len(latestfiles) < 2:
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (pn, taskname))
sys.exit(1)
else:
filedates = find_siginfo(bbhandler, pn, taskname)
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-3:]
if not latestfiles:
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
sys.exit(1)
elif len(latestfiles) < 2:
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (pn, taskname))
sys.exit(1)
# It's possible that latestfiles contain 3 elements and the first two have the same hash value.
# In this case, we delete the second element.
# The above case is actually the most common one. Because we may have sigdata file and siginfo
# file having the same hash value. Comparing such two files makes no sense.
if len(latestfiles) == 3:
hash0 = get_hashval(latestfiles[0])
hash1 = get_hashval(latestfiles[1])
if hash0 == hash1:
latestfiles.pop(1)
# Define recursion callback
def recursecb(key, hash1, hash2):
hashes = [hash1, hash2]
hashfiles = find_siginfo(bbhandler, key, None, hashes)
# Define recursion callback
def recursecb(key, hash1, hash2):
hashes = [hash1, hash2]
hashfiles = bb.siggen.find_siginfo(key, None, hashes, bbhandler.config_data)
recout = []
if len(hashfiles) == 0:
recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
elif not hash1 in hashfiles:
recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash1))
elif not hash2 in hashfiles:
recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash2))
else:
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb, color=color)
for change in out2:
for line in change.splitlines():
recout.append(' ' + line)
recout = []
if len(hashfiles) == 2:
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb)
recout.extend(list(' ' + l for l in out2))
else:
recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
return recout
return recout
# Recurse into signature comparison
logger.debug("Signature file (previous): %s" % latestfiles[-2])
logger.debug("Signature file (latest): %s" % latestfiles[-1])
output = bb.siggen.compare_sigfiles(latestfiles[-2], latestfiles[-1], recursecb, color=color)
if output:
print('\n'.join(output))
# Recurse into signature comparison
output = bb.siggen.compare_sigfiles(latestfiles[0], latestfiles[1], recursecb)
if output:
print('\n'.join(output))
sys.exit(0)
parser = argparse.ArgumentParser(
description="Compares siginfo/sigdata files written out by BitBake")
parser = optparse.OptionParser(
description = "Compares siginfo/sigdata files written out by BitBake",
usage = """
%prog -t recipename taskname
%prog sigdatafile1 sigdatafile2
%prog sigdatafile1""")
parser.add_argument('-d', '--debug',
help='Enable debug output',
action='store_true')
parser.add_option("-t", "--task",
help = "find the signature data files for last two runs of the specified task and compare them",
action="store", dest="taskargs", nargs=2, metavar='recipename taskname')
parser.add_argument('--color',
help='Colorize output (where %(metavar)s is %(choices)s)',
choices=['auto', 'always', 'never'], default='auto', metavar='color')
parser.add_argument("-t", "--task",
help="find the signature data files for last two runs of the specified task and compare them",
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
parser.add_argument("-s", "--signature",
help="With -t/--task, specify the signatures to look for instead of taking the last two",
action="store", dest="sigargs", nargs=2, metavar=('fromsig', 'tosig'))
parser.add_argument("sigdatafile1",
help="First signature file to compare (or signature file to dump, if second not specified). Not used when using -t/--task.",
action="store", nargs='?')
parser.add_argument("sigdatafile2",
help="Second signature file to compare",
action="store", nargs='?')
options = parser.parse_args()
if options.debug:
logger.setLevel(logging.DEBUG)
color = (options.color == 'always' or (options.color == 'auto' and sys.stdout.isatty()))
options, args = parser.parse_args(sys.argv)
if options.taskargs:
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare(config_only=True)
if options.sigargs:
find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0], options.sigargs[1], color=color)
else:
find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1], color=color)
find_compare_task(tinfoil, options.taskargs[0], options.taskargs[1])
else:
if options.sigargs:
logger.error('-s/--signature can only be used together with -t/--task')
sys.exit(1)
try:
if options.sigdatafile1 and options.sigdatafile2:
output = bb.siggen.compare_sigfiles(options.sigdatafile1, options.sigdatafile2, color=color)
elif options.sigdatafile1:
output = bb.siggen.dump_sigfile(options.sigdatafile1)
else:
logger.error('Must specify signature file(s) or -t/--task')
parser.print_help()
if len(args) == 1:
parser.print_help()
else:
try:
if len(args) == 2:
output = bb.siggen.dump_sigfile(sys.argv[1])
else:
output = bb.siggen.compare_sigfiles(sys.argv[1], sys.argv[2])
except IOError as e:
logger.error(str(e))
sys.exit(1)
except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying sigdata/siginfo files')
sys.exit(1)
except IOError as e:
logger.error(str(e))
sys.exit(1)
except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying sigdata/siginfo files')
sys.exit(1)
if output:
print('\n'.join(output))
if output:
print('\n'.join(output))

View File

@@ -27,68 +27,39 @@ import pickle
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb.tinfoil
import bb.siggen
import bb.msg
logger = bb.msg.logger_create('bitbake-dumpsig')
def logger_create(name, output=sys.stderr):
logger = logging.getLogger(name)
console = logging.StreamHandler(output)
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
if output.isatty():
format.enable_color()
console.setFormatter(format)
logger.addHandler(console)
logger.setLevel(logging.INFO)
return logger
def find_siginfo_task(bbhandler, pn, taskname):
""" Find the most recent signature file for the specified PN/task """
if not hasattr(bb.siggen, 'find_siginfo'):
logger.error('Metadata does not support finding signature data files')
sys.exit(1)
if not taskname.startswith('do_'):
taskname = 'do_%s' % taskname
filedates = bb.siggen.find_siginfo(pn, taskname, None, bbhandler.config_data)
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-1:]
if not latestfiles:
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
sys.exit(1)
return latestfiles[0]
logger = logger_create('bitbake-dumpsig')
parser = optparse.OptionParser(
description = "Dumps siginfo/sigdata files written out by BitBake",
usage = """
%prog -t recipename taskname
%prog sigdatafile""")
parser.add_option("-D", "--debug",
help = "enable debug",
action = "store_true", dest="debug", default = False)
parser.add_option("-t", "--task",
help = "find the signature data file for the specified task",
action="store", dest="taskargs", nargs=2, metavar='recipename taskname')
options, args = parser.parse_args(sys.argv)
if options.debug:
logger.setLevel(logging.DEBUG)
if options.taskargs:
tinfoil = bb.tinfoil.Tinfoil()
tinfoil.prepare(config_only = True)
file = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1])
logger.debug("Signature file: %s" % file)
elif len(args) == 1:
if len(args) == 1:
parser.print_help()
sys.exit(0)
else:
file = args[1]
try:
output = bb.siggen.dump_sigfile(args[1])
except IOError as e:
logger.error(str(e))
sys.exit(1)
except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying a sigdata/siginfo file')
sys.exit(1)
try:
output = bb.siggen.dump_sigfile(file)
except IOError as e:
logger.error(str(e))
sys.exit(1)
except (pickle.UnpicklingError, EOFError):
logger.error('Invalid signature data - ensure you are specifying a sigdata/siginfo file')
sys.exit(1)
if output:
print('\n'.join(output))
if output:
print('\n'.join(output))

View File

@@ -24,26 +24,49 @@ import logging
import os
import sys
import argparse
import signal
bindir = os.path.dirname(__file__)
topdir = os.path.dirname(bindir)
sys.path[0:0] = [os.path.join(topdir, 'lib')]
import bb.tinfoil
import bb.msg
logger = bb.msg.logger_create('bitbake-layers', sys.stdout)
def tinfoil_init(parserecipes):
import bb.tinfoil
tinfoil = bb.tinfoil.Tinfoil(tracking=True)
tinfoil.prepare(not parserecipes)
tinfoil.logger.setLevel(logger.getEffectiveLevel())
return tinfoil
def logger_create(name, output=sys.stderr):
logger = logging.getLogger(name)
loggerhandler = logging.StreamHandler(output)
loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
logger.addHandler(loggerhandler)
logger.setLevel(logging.INFO)
return logger
def logger_setup_color(logger, color='auto'):
from bb.msg import BBLogFormatter
console = logging.StreamHandler(sys.stdout)
formatter = BBLogFormatter("%(levelname)s: %(message)s")
console.setFormatter(formatter)
logger.handlers = [console]
if color == 'always' or (color == 'auto' and console.stream.isatty()):
formatter.enable_color()
logger = 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",
add_help=False)
parser.add_argument('-d', '--debug', help='Enable debug output', action='store_true')
parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
parser.add_argument('-F', '--force', help='Force add without recipe parse verification', action='store_true')
parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
global_args, unparsed_args = parser.parse_known_args()
@@ -60,17 +83,13 @@ def main():
elif global_args.quiet:
logger.setLevel(logging.ERROR)
# Need to re-run logger_create with color argument
# (will be the same logger since it has the same name)
bb.msg.logger_create('bitbake-layers', output=sys.stdout, color=global_args.color)
logger_setup_color(logger, global_args.color)
plugins = []
tinfoil = bb.tinfoil.Tinfoil(tracking=True)
tinfoil.logger.setLevel(logger.getEffectiveLevel())
tinfoil = tinfoil_init(False)
try:
tinfoil.prepare(True)
for path in ([topdir] +
tinfoil.config_data.getVar('BBPATH').split(':')):
tinfoil.config_data.getVar('BBPATH', True).split(':')):
pluginpath = os.path.join(path, 'lib', 'bblayers')
bb.utils.load_plugins(logger, plugins, pluginpath)
@@ -90,7 +109,7 @@ def main():
if getattr(args, 'parserecipes', False):
tinfoil.config_data.disableTracking()
tinfoil.parse_recipes()
tinfoil.parseRecipes()
tinfoil.config_data.enableTracking()
return args.func(args)

View File

@@ -28,7 +28,6 @@ except RuntimeError as exc:
tests = ["bb.tests.codeparser",
"bb.tests.cow",
"bb.tests.data",
"bb.tests.event",
"bb.tests.fetch",
"bb.tests.parse",
"bb.tests.utils"]

View File

@@ -17,7 +17,7 @@ from multiprocessing import Lock
from threading import Thread
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.")
sys.exit("Please use a locale setting which supports 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) != 2 or not sys.argv[1].startswith("decafbad"):
@@ -95,7 +95,6 @@ def worker_flush(worker_queue):
pass
while (worker_queue_int or not worker_queue.empty()):
try:
(_, ready, _) = select.select([], [worker_pipe], [], 1)
if not worker_queue.empty():
worker_queue_int = worker_queue_int + worker_queue.get()
written = os.write(worker_pipe, worker_queue_int)
@@ -136,7 +135,7 @@ def sigterm_handler(signum, frame):
os.killpg(0, signal.SIGTERM)
sys.exit()
def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, appends, taskdepdata, extraconfigdata, quieterrors=False, dry_run_exec=False):
def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, appends, taskdepdata, quieterrors=False):
# We need to setup the environment BEFORE the fork, since
# a fork() or exec*() activates PSEUDO...
@@ -152,10 +151,8 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, append
except TypeError:
umask = taskdep['umask'][taskname]
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:
if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not cfg.dry_run:
envvars = (workerdata["fakerootenv"][fn] or "").split()
for key, value in (var.split('=') for var in envvars):
envbackup[key] = os.environ.get(key)
@@ -222,21 +219,16 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, append
the_data = databuilder.mcdata[mc]
the_data.setVar("BB_WORKERCONTEXT", "1")
the_data.setVar("BB_TASKDEPDATA", taskdepdata)
if cfg.limited_deps:
the_data.setVar("BB_LIMITEDDEPS", "1")
the_data.setVar("BUILDNAME", workerdata["buildname"])
the_data.setVar("DATE", workerdata["date"])
the_data.setVar("TIME", workerdata["time"])
for varname, value in extraconfigdata.items():
the_data.setVar(varname, value)
bb.parse.siggen.set_taskdata(workerdata["sigdata"])
ret = 0
the_data = bb_cache.loadDataFull(fn, appends)
the_data.setVar('BB_TASKHASH', workerdata["runq_hash"][task])
bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN"), taskname.replace("do_", "")))
bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN", True), taskname.replace("do_", "")))
# exported_vars() returns a generator which *cannot* be passed to os.environ.update()
# successfully. We also need to unset anything from the environment which shouldn't be there
@@ -251,11 +243,11 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, append
the_data.setVar(e, fakeenv[e])
the_data.setVarFlag(e, 'export', "1")
task_exports = the_data.getVarFlag(taskname, 'exports')
task_exports = the_data.getVarFlag(taskname, 'exports', True)
if task_exports:
for e in task_exports.split():
the_data.setVarFlag(e, 'export', '1')
v = the_data.getVar(e)
v = the_data.getVar(e, True)
if v is not None:
os.environ[e] = v
@@ -267,7 +259,7 @@ def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, append
logger.critical(traceback.format_exc())
os._exit(1)
try:
if dry_run:
if cfg.dry_run:
return 0
return bb.build.exec_task(fn, taskname, the_data, cfg.profile)
except:
@@ -336,7 +328,6 @@ class BitbakeWorker(object):
self.cookercfg = None
self.databuilder = None
self.data = None
self.extraconfigdata = None
self.build_pids = {}
self.build_pipes = {}
@@ -371,7 +362,6 @@ class BitbakeWorker(object):
pass
if len(self.queue):
self.handle_item(b"cookerconfig", self.handle_cookercfg)
self.handle_item(b"extraconfigdata", self.handle_extraconfigdata)
self.handle_item(b"workerdata", self.handle_workerdata)
self.handle_item(b"runtask", self.handle_runtask)
self.handle_item(b"finishnow", self.handle_finishnow)
@@ -379,11 +369,9 @@ class BitbakeWorker(object):
self.handle_item(b"quit", self.handle_quit)
for pipe in self.build_pipes:
if self.build_pipes[pipe].input in ready:
self.build_pipes[pipe].read()
self.build_pipes[pipe].read()
if len(self.build_pids):
while self.process_waitpid():
continue
self.process_waitpid()
def handle_item(self, item, func):
@@ -400,9 +388,6 @@ class BitbakeWorker(object):
self.databuilder.parseBaseConfiguration()
self.data = self.databuilder.data
def handle_extraconfigdata(self, data):
self.extraconfigdata = pickle.loads(data)
def handle_workerdata(self, data):
self.workerdata = pickle.loads(data)
bb.msg.loggerDefaultDebugLevel = self.workerdata["logdefaultdebug"]
@@ -425,10 +410,10 @@ class BitbakeWorker(object):
sys.exit(0)
def handle_runtask(self, data):
fn, task, taskname, quieterrors, appends, taskdepdata, dry_run_exec = pickle.loads(data)
fn, task, taskname, quieterrors, appends, taskdepdata = pickle.loads(data)
workerlog_write("Handling runtask %s %s %s\n" % (task, fn, taskname))
pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.databuilder, self.workerdata, fn, task, taskname, appends, taskdepdata, self.extraconfigdata, quieterrors, dry_run_exec)
pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.databuilder, self.workerdata, fn, task, taskname, appends, taskdepdata, quieterrors)
self.build_pids[pid] = task
self.build_pipes[pid] = runQueueWorkerPipe(pipein, pipeout)
@@ -441,9 +426,9 @@ class BitbakeWorker(object):
try:
pid, status = os.waitpid(-1, os.WNOHANG)
if pid == 0 or os.WIFSTOPPED(status):
return False
return None
except OSError:
return False
return None
workerlog_write("Exit code of %s for pid %s\n" % (status, pid))
@@ -462,8 +447,6 @@ class BitbakeWorker(object):
worker_fire_prepickled(b"<exitcode>" + pickle.dumps((task, status)) + b"</exitcode>")
return True
def handle_finishnow(self, _):
if self.build_pids:
logger.info("Sending SIGTERM to remaining %s tasks", len(self.build_pids))
@@ -499,3 +482,4 @@ worker_thread.join()
workerlog_write("exitting")
sys.exit(0)

View File

@@ -1,165 +0,0 @@
#!/usr/bin/env python3
"""git-make-shallow: make the current git repository shallow
Remove the history of the specified revisions, then optionally filter the
available refs to those specified.
"""
import argparse
import collections
import errno
import itertools
import os
import subprocess
import sys
version = 1.0
def main():
if sys.version_info < (3, 4, 0):
sys.exit('Python 3.4 or greater is required')
git_dir = check_output(['git', 'rev-parse', '--git-dir']).rstrip()
shallow_file = os.path.join(git_dir, 'shallow')
if os.path.exists(shallow_file):
try:
check_output(['git', 'fetch', '--unshallow'])
except subprocess.CalledProcessError:
try:
os.unlink(shallow_file)
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
args = process_args()
revs = check_output(['git', 'rev-list'] + args.revisions).splitlines()
make_shallow(shallow_file, args.revisions, args.refs)
ref_revs = check_output(['git', 'rev-list'] + args.refs).splitlines()
remaining_history = set(revs) & set(ref_revs)
for rev in remaining_history:
if check_output(['git', 'rev-parse', '{}^@'.format(rev)]):
sys.exit('Error: %s was not made shallow' % rev)
filter_refs(args.refs)
if args.shrink:
shrink_repo(git_dir)
subprocess.check_call(['git', 'fsck', '--unreachable'])
def process_args():
# TODO: add argument to automatically keep local-only refs, since they
# can't be easily restored with a git fetch.
parser = argparse.ArgumentParser(description='Remove the history of the specified revisions, then optionally filter the available refs to those specified.')
parser.add_argument('--ref', '-r', metavar='REF', action='append', dest='refs', help='remove all but the specified refs (cumulative)')
parser.add_argument('--shrink', '-s', action='store_true', help='shrink the git repository by repacking and pruning')
parser.add_argument('revisions', metavar='REVISION', nargs='+', help='a git revision/commit')
if len(sys.argv) < 2:
parser.print_help()
sys.exit(2)
args = parser.parse_args()
if args.refs:
args.refs = check_output(['git', 'rev-parse', '--symbolic-full-name'] + args.refs).splitlines()
else:
args.refs = get_all_refs(lambda r, t, tt: t == 'commit' or tt == 'commit')
args.refs = list(filter(lambda r: not r.endswith('/HEAD'), args.refs))
args.revisions = check_output(['git', 'rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines()
return args
def check_output(cmd, input=None):
return subprocess.check_output(cmd, universal_newlines=True, input=input)
def make_shallow(shallow_file, revisions, refs):
"""Remove the history of the specified revisions."""
for rev in follow_history_intersections(revisions, refs):
print("Processing %s" % rev)
with open(shallow_file, 'a') as f:
f.write(rev + '\n')
def get_all_refs(ref_filter=None):
"""Return all the existing refs in this repository, optionally filtering the refs."""
ref_output = check_output(['git', 'for-each-ref', '--format=%(refname)\t%(objecttype)\t%(*objecttype)'])
ref_split = [tuple(iter_extend(l.rsplit('\t'), 3)) for l in ref_output.splitlines()]
if ref_filter:
ref_split = (e for e in ref_split if ref_filter(*e))
refs = [r[0] for r in ref_split]
return refs
def iter_extend(iterable, length, obj=None):
"""Ensure that iterable is the specified length by extending with obj."""
return itertools.islice(itertools.chain(iterable, itertools.repeat(obj)), length)
def filter_refs(refs):
"""Remove all but the specified refs from the git repository."""
all_refs = get_all_refs()
to_remove = set(all_refs) - set(refs)
if to_remove:
check_output(['xargs', '-0', '-n', '1', 'git', 'update-ref', '-d', '--no-deref'],
input=''.join(l + '\0' for l in to_remove))
def follow_history_intersections(revisions, refs):
"""Determine all the points where the history of the specified revisions intersects the specified refs."""
queue = collections.deque(revisions)
seen = set()
for rev in iter_except(queue.popleft, IndexError):
if rev in seen:
continue
parents = check_output(['git', 'rev-parse', '%s^@' % rev]).splitlines()
yield rev
seen.add(rev)
if not parents:
continue
check_refs = check_output(['git', 'merge-base', '--independent'] + sorted(refs)).splitlines()
for parent in parents:
for ref in check_refs:
print("Checking %s vs %s" % (parent, ref))
try:
merge_base = check_output(['git', 'merge-base', parent, ref]).rstrip()
except subprocess.CalledProcessError:
continue
else:
queue.append(merge_base)
def iter_except(func, exception, start=None):
"""Yield a function repeatedly until it raises an exception."""
try:
if start is not None:
yield start()
while True:
yield func()
except exception:
pass
def shrink_repo(git_dir):
"""Shrink the newly shallow repository, removing the unreachable objects."""
subprocess.check_call(['git', 'reflog', 'expire', '--expire-unreachable=now', '--all'])
subprocess.check_call(['git', 'repack', '-ad'])
try:
os.unlink(os.path.join(git_dir, 'objects', 'info', 'alternates'))
except OSError as exc:
if exc.errno != errno.ENOENT:
raise
subprocess.check_call(['git', 'prune', '--expire', 'now'])
if __name__ == '__main__':
main()

View File

@@ -18,23 +18,35 @@
# along with this program. If not, see http://www.gnu.org/licenses/.
HELP="
Usage: source toaster start|stop [webport=<address:port>] [noweb] [nobuild]
Usage: source toaster start|stop [webport=<address:port>] [noweb]
Optional arguments:
[nobuild] Setup the environment for capturing builds with toaster but disable managed builds
[noweb] Setup the environment for capturing builds with toaster but don't start the web server
[noweb] Setup the environment for building with toaster but don't start the development server
[webport] Set the development server (default: localhost:8000)
"
custom_extention()
webserverKillAll()
{
custom_extension=$BBBASEDIR/lib/toaster/orm/fixtures/custom_toaster_append.sh
if [ -f $custom_extension ] ; then
$custom_extension $*
fi
local pidfile
for pidfile in ${BUILDDIR}/.toastermain.pid ${BUILDDIR}/.runbuilds.pid; do
if [ -f ${pidfile} ]; then
pid=`cat ${pidfile}`
while kill -0 $pid 2>/dev/null; do
kill -SIGTERM -$pid 2>/dev/null
sleep 1
done
rm ${pidfile}
fi
done
}
databaseCheck()
webserverStartAll()
{
# do not start if toastermain points to a valid process
if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
retval=1
rm "${BUILDDIR}/.toastermain.pid"
fi
retval=0
# you can always add a superuser later via
# ../bitbake/lib/toaster/manage.py createsuperuser --username=<ME>
@@ -53,45 +65,9 @@ databaseCheck()
return $retval
fi
return $retval
}
webserverKillAll()
{
local pidfile
if [ -f ${BUILDDIR}/.toastermain.pid ] ; then
custom_extention web_stop_postpend
else
custom_extention noweb_stop_postpend
fi
for pidfile in ${BUILDDIR}/.toastermain.pid ${BUILDDIR}/.runbuilds.pid; do
if [ -f ${pidfile} ]; then
pid=`cat ${pidfile}`
while kill -0 $pid 2>/dev/null; do
kill -SIGTERM $pid 2>/dev/null
sleep 1
done
rm ${pidfile}
fi
done
}
webserverStartAll()
{
# do not start if toastermain points to a valid process
if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
retval=1
rm "${BUILDDIR}/.toastermain.pid"
fi
retval=0
# check the database
databaseCheck || return 1
echo "Starting webserver..."
$MANAGE runserver --noreload "$ADDR_PORT" \
$MANAGE runserver "$ADDR_PORT" \
</dev/null >>${BUILDDIR}/toaster_web.log 2>&1 \
& echo $! >${BUILDDIR}/.toastermain.pid
@@ -103,7 +79,6 @@ webserverStartAll()
else
echo "Toaster development webserver started at http://$ADDR_PORT"
echo -e "\nYou can now run 'bitbake <target>' on the command line and monitor your build in Toaster.\nYou can also use a Toaster project to configure and run a build.\n"
custom_extention web_start_postpend $ADDR_PORT
fi
return $retval
@@ -131,18 +106,12 @@ verify_prereq() {
# Verify Django version
reqfile=$(python3 -c "import os; print(os.path.realpath('$BBBASEDIR/toaster-requirements.txt'))")
exp='s/Django\([><=]\+\)\([^,]\+\),\([><=]\+\)\(.\+\)/'
# expand version parts to 2 digits to support 1.10.x > 1.8
# (note:helper functions hard to insert in-line)
exp=$exp'import sys,django;'
exp=$exp'version=["%02d" % int(n) for n in django.get_version().split(".")];'
exp=$exp'vmin=["%02d" % int(n) for n in "\2".split(".")];'
exp=$exp'vmax=["%02d" % int(n) for n in "\4".split(".")];'
exp=$exp'sys.exit(not (version \1 vmin and version \3 vmax))'
exp=$exp'/p'
exp=$exp'import sys,django;version=django.get_version().split(".");'
exp=$exp'sys.exit(not (version \1 "\2".split(".") and version \3 "\4".split(".")))/p'
if ! sed -n "$exp" $reqfile | python3 - ; then
req=`grep ^Django $reqfile`
echo "This program needs $req"
echo "Please install with pip3 install -r $reqfile"
echo "Please install with pip install -r $reqfile"
return 2
fi
@@ -182,9 +151,16 @@ fi
unset OE_ROOT
# this defines the dir toaster will use for
# 1) clones of layers (in _toaster_clones )
# 2) the build dir (in build)
# 3) the sqlite db if that is being used.
# 4) pid's we need to clean up on exit/shutdown
# note: for future. in order to make this an arbitrary directory, we need to
# make sure that the toaster.sqlite file doesn't default to `pwd` like it currently does.
export TOASTER_DIR=`pwd`
WEBSERVER=1
export TOASTER_BUILDSERVER=1
ADDR_PORT="localhost:8000"
unset CMD
for param in $*; do
@@ -192,9 +168,6 @@ for param in $*; do
noweb )
WEBSERVER=0
;;
nobuild )
TOASTER_BUILDSERVER=0
;;
start )
CMD=$param
;;
@@ -241,8 +214,10 @@ fi
# 2) the build dir (in build)
# 3) the sqlite db if that is being used.
# 4) pid's we need to clean up on exit/shutdown
# note: for future. in order to make this an arbitrary directory, we need to
# make sure that the toaster.sqlite file doesn't default to `pwd`
# like it currently does.
export TOASTER_DIR=`dirname $BUILDDIR`
export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE TOASTER_DIR"
# Determine the action. If specified by arguments, fine, if not, toggle it
if [ "$CMD" = "start" ] ; then
@@ -259,7 +234,6 @@ fi
echo "The system will $CMD."
# Execute the commands
custom_extention toaster_prepend $CMD $ADDR_PORT
case $CMD in
start )
@@ -275,34 +249,15 @@ case $CMD in
line='INHERIT+="toaster buildhistory"'
grep -q "$line" $conf || echo $line >> $conf
if [ $WEBSERVER -eq 0 ] ; then
# Do not update the database for "noweb" unless
# it does not yet exist
if [ ! -f "$TOASTER_DIR/toaster.sqlite" ] ; then
if ! databaseCheck; then
echo "Failed ${CMD}."
return 4
fi
fi
custom_extention noweb_start_postpend $ADDR_PORT
fi
if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
echo "Failed ${CMD}."
return 4
fi
export BITBAKE_UI='toasterui'
if [ $TOASTER_BUILDSERVER -eq 1 ] ; then
$MANAGE runbuilds \
</dev/null >>${BUILDDIR}/toaster_runbuilds.log 2>&1 \
& echo $! >${BUILDDIR}/.runbuilds.pid
else
echo "Toaster build server not started."
fi
$MANAGE runbuilds & echo $! >${BUILDDIR}/.runbuilds.pid
# set fail safe stop system on terminal exit
trap stop_system SIGHUP
echo "Successful ${CMD}."
custom_extention toaster_postpend $CMD $ADDR_PORT
return 0
;;
stop )
@@ -310,5 +265,3 @@ case $CMD in
echo "Successful ${CMD}."
;;
esac
custom_extention toaster_postpend $CMD $ADDR_PORT

View File

@@ -2,7 +2,7 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2012, 2018 Wind River Systems, Inc.
# Copyright (C) 2012 Wind River Systems, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -18,68 +18,51 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Used for dumping the bb_cache.dat
# This is used for dumping the bb_cache.dat, the output format is:
# recipe_path PN PV PACKAGES
#
import os
import sys
import argparse
import warnings
# For importing bb.cache
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), '../lib'))
from bb.cache import CoreRecipeInfo
import pickle
import pickle as pickle
class DumpCache(object):
def __init__(self):
parser = argparse.ArgumentParser(
description="bb_cache.dat's dumper",
epilog="Use %(prog)s --help to get help")
parser.add_argument("-r", "--recipe",
help="specify the recipe, default: all recipes", action="store")
parser.add_argument("-m", "--members",
help = "specify the member, use comma as separator for multiple ones, default: all members", action="store", default="")
parser.add_argument("-s", "--skip",
help = "skip skipped recipes", action="store_true")
parser.add_argument("cachefile",
help = "specify bb_cache.dat", nargs = 1, action="store", default="")
def main(argv=None):
"""
Get the mapping for the target recipe.
"""
if len(argv) != 1:
print("Error, need one argument!", file=sys.stderr)
return 2
self.args = parser.parse_args()
cachefile = argv[0]
def main(self):
with open(self.args.cachefile[0], "rb") as cachefile:
pickled = pickle.Unpickler(cachefile)
while True:
try:
key = pickled.load()
val = pickled.load()
except Exception:
break
if isinstance(val, CoreRecipeInfo):
pn = val.pn
with open(cachefile, "rb") as cachefile:
pickled = pickle.Unpickler(cachefile)
while cachefile:
try:
key = pickled.load()
val = pickled.load()
except Exception:
break
if isinstance(val, CoreRecipeInfo) and (not val.skipped):
pn = val.pn
# Filter out the native recipes.
if key.startswith('virtual:native:') or pn.endswith("-native"):
continue
if self.args.recipe and self.args.recipe != pn:
continue
# 1.0 is the default version for a no PV recipe.
if "pv" in val.__dict__:
pv = val.pv
else:
pv = "1.0"
if self.args.skip and val.skipped:
continue
if self.args.members:
out = key
for member in self.args.members.split(','):
out += ": %s" % val.__dict__.get(member)
print("%s" % out)
else:
print("%s: %s" % (key, val.__dict__))
elif not self.args.recipe:
print("%s %s" % (key, val))
print("%s %s %s %s" % (key, pn, pv, ' '.join(val.packages)))
if __name__ == "__main__":
try:
dump = DumpCache()
ret = dump.main()
except Exception as esc:
ret = 1
import traceback
traceback.print_exc()
sys.exit(ret)
sys.exit(main(sys.argv[1:]))

View File

@@ -781,7 +781,7 @@
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
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.

View File

@@ -38,7 +38,7 @@
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()
src_uri = (d.getVar('SRC_URI', True) or "").split()
fetcher = bb.fetch2.Fetch(src_uri, d)
fetcher.download()
</literallayout>
@@ -52,7 +52,7 @@
<para>
The instantiation of the fetch class is usually followed by:
<literallayout class='monospaced'>
rootdir = l.getVar('WORKDIR')
rootdir = l.getVar('WORKDIR', True)
fetcher.unpack(rootdir)
</literallayout>
This code unpacks the downloaded files to the
@@ -268,6 +268,15 @@
<link linkend='var-FILESPATH'><filename>FILESPATH</filename></link>
variable is used in the same way
<filename>PATH</filename> is used to find executables.
Failing that,
<link linkend='var-FILESDIR'><filename>FILESDIR</filename></link>
is used to find the appropriate relative file.
<note>
<filename>FILESDIR</filename> is deprecated and can
be replaced with <filename>FILESPATH</filename>.
Because <filename>FILESDIR</filename> is likely to be
removed, you should not use this variable in any new code.
</note>
If the file cannot be found, it is assumed that it is available in
<link linkend='var-DL_DIR'><filename>DL_DIR</filename></link>
by the time the <filename>download()</filename> method is called.
@@ -376,8 +385,7 @@
The supported parameters are as follows:
<itemizedlist>
<listitem><para><emphasis>"method":</emphasis>
The protocol over which to communicate with the CVS
server.
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>.
@@ -461,29 +469,25 @@
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.
Other options are "svn+ssh" and "rsh".
For "rsh", the "rsh" parameter is also used.
</para></listitem>
<listitem><para><emphasis>"rev":</emphasis>
The revision of the source code to checkout.
</para></listitem>
<listitem><para><emphasis>"date":</emphasis>
The date of the source code to checkout.
Specific revisions are generally much safer to checkout
rather than by date as they do not involve timezones
(e.g. they are much more deterministic).
</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.
@@ -492,11 +496,10 @@
command.
</para></listitem>
</itemizedlist>
Following are three examples using svn:
Following are two 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"
SRC_URI = "svn://svn.oe.handhelds.org/svn;module=vip;proto=http;rev=667"
SRC_URI = "svn://svn.oe.handhelds.org/svn/;module=opie;proto=svn+ssh;date=20060126"
</literallayout>
</para>
</section>
@@ -620,9 +623,7 @@
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.
normal source mirroring infrastructure properly.
</para>
</note>
</para>
@@ -777,43 +778,6 @@
</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-REPODIR'><filename>REPODIR</filename></link>,
which is usually
<link linkend='var-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>
@@ -832,6 +796,9 @@
<listitem><para>
Secure Shell (<filename>ssh://</filename>)
</para></listitem>
<listitem><para>
Repo (<filename>repo://</filename>)
</para></listitem>
<listitem><para>
OSC (<filename>osc://</filename>)
</para></listitem>

View File

@@ -128,8 +128,15 @@
</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>.
This example was inspired by and drew heavily from these sources:
<itemizedlist>
<listitem><para>
<ulink url="http://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html">Mailing List post - The BitBake equivalent of "Hello, World!"</ulink>
</para></listitem>
<listitem><para>
<ulink url="http://hambedded.org/blog/2012/11/24/from-bitbake-hello-world-to-an-image/">Hambedded Linux blog post - From Bitbake Hello World to an Image</ulink>
</para></listitem>
</itemizedlist>
</note>
<para>
@@ -260,9 +267,9 @@
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,
For more information on the <filename>bitbake.conf</filename>,
see
<ulink url='http://git.openembedded.org/bitbake/tree/conf/bitbake.conf'></ulink>.
<ulink url='http://hambedded.org/blog/2012/11/24/from-bitbake-hello-world-to-an-image/#an-overview-of-bitbakeconf'></ulink>
</para>
<para>Use the following commands to create the <filename>conf</filename>
directory in the project directory:
@@ -273,32 +280,14 @@
some editor to create the <filename>bitbake.conf</filename>
so that it contains the following:
<literallayout class='monospaced'>
<link linkend='var-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-TOPDIR'>TOPDIR</link>}/tmp"
<link linkend='var-CACHE'>CACHE</link> = "${TMPDIR}/cache"
<link linkend='var-STAMP'>STAMP</link> = "${TMPDIR}/${PN}/stamps"
<link linkend='var-T'>T</link> = "${TMPDIR}/${PN}/work"
<link linkend='var-B'>B</link> = "${TMPDIR}/${PN}"
<link linkend='var-STAMP'>STAMP</link> = "${TMPDIR}/stamps"
<link linkend='var-T'>T</link> = "${TMPDIR}/work"
<link linkend='var-B'>B</link> = "${TMPDIR}"
</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
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
@@ -318,19 +307,19 @@
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
$ 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
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.
@@ -363,6 +352,9 @@
Of course, the <filename>base.bbclass</filename> can have much
more depending on which build environments BitBake is
supporting.
For more information on the <filename>base.bbclass</filename> file,
you can look at
<ulink url='http://hambedded.org/blog/2012/11/24/from-bitbake-hello-world-to-an-image/#tasks'></ulink>.
</para></listitem>
<listitem><para><emphasis>Run Bitbake:</emphasis>
After making sure that the <filename>classes/base.bbclass</filename>
@@ -383,10 +375,10 @@
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>
You can find additional information on adding a layer at
<ulink url='http://hambedded.org/blog/2012/11/24/from-bitbake-hello-world-to-an-image/#adding-an-example-layer'></ulink>.
</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>

View File

@@ -440,7 +440,7 @@
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.
system, such as Poky or Yocto Project.
Rather than manually checking out individual layers and
gluing them together yourself, you can check
out an entire build system.
@@ -488,6 +488,8 @@
target that failed and anything depending on it cannot
be built, as much as possible will be built before
stopping.
-a, --tryaltconfigs Continue with builds by trying to use alternative
providers where possible.
-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
@@ -502,20 +504,9 @@
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;).
-v, --verbose Output more log message data to the terminal.
-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.
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
@@ -538,38 +529,29 @@
-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).
-u UI, --ui=UI The user interface to use (depexp, goggle, hob, knotty
or ncurses - default knotty).
-t SERVERTYPE, --servertype=SERVERTYPE
Choose which server type to use (process or xmlrpc -
default process).
--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.
-B BIND, --bind=BIND The name/address for the bitbake server to bind to.
--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.
-m, --kill-server Terminate the remote 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>
@@ -683,21 +665,21 @@
</para>
<para>
When you generate a dependency graph, BitBake writes three files
When you generate a dependency graph, BitBake writes four files
to the current working directory:
<itemizedlist>
<listitem><para>
<emphasis><filename>recipe-depends.dot</filename>:</emphasis>
Shows dependencies between recipes (i.e. a collapsed version of
<filename>task-depends.dot</filename>).
<listitem><para><emphasis><filename>package-depends.dot</filename>:</emphasis>
Shows BitBake's knowledge of dependencies between
runtime targets.
</para></listitem>
<listitem><para>
<emphasis><filename>task-depends.dot</filename>:</emphasis>
<listitem><para><emphasis><filename>pn-depends.dot</filename>:</emphasis>
Shows dependencies between build-time targets
(i.e. recipes).
</para></listitem>
<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>
<listitem><para><emphasis><filename>pn-buildlist</filename>:</emphasis>
Shows a simple list of targets that are to be built.
</para></listitem>
</itemizedlist>

View File

@@ -61,48 +61,6 @@
</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>
@@ -505,14 +463,14 @@
<title>Unseting variables</title>
<para>
It is possible to completely remove a variable or a variable flag
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
These two statements remove the <filename>DATE</filename> and the
<filename>do_fetch[noexec]</filename> flag.
</para>
@@ -669,7 +627,7 @@
<literallayout class='monospaced'>
DEPENDS = "glibc ncurses"
OVERRIDES = "machine:local"
DEPENDS_append_machine = " libmad"
DEPENDS_append_machine = "libmad"
</literallayout>
In this example, <filename>DEPENDS</filename> becomes
"glibc ncurses libmad".
@@ -899,12 +857,11 @@
<para>
The <filename>inherit</filename> directive is a rudimentary
means of specifying functionality contained in class files
that your recipes require.
means of specifying what classes of functionality 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.
those tasks into a class file that can be used by your recipe.
</para>
<para>
@@ -923,24 +880,13 @@
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.
If necessary, it is possible to inherit a class
conditionally by using
a variable expression after the <filename>inherit</filename>
statement.
Here is an example:
<literallayout class='monospaced'>
inherit ${VARNAME}
@@ -996,17 +942,6 @@
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:
@@ -1040,18 +975,6 @@
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>,
@@ -1084,9 +1007,8 @@
<para>
When creating a configuration file (<filename>.conf</filename>),
you can use the
<link linkend='var-INHERIT'><filename>INHERIT</filename></link>
configuration directive to inherit a class.
you can use the <filename>INHERIT</filename> directive to
inherit a class.
BitBake only supports this directive when used within
a configuration file.
</para>
@@ -1119,7 +1041,7 @@
<filename>autotools</filename> and <filename>pkgconfig</filename>
classes:
<literallayout class='monospaced'>
INHERIT += "autotools pkgconfig"
inherit autotools pkgconfig
</literallayout>
</para>
</section>
@@ -1243,7 +1165,7 @@
<literallayout class='monospaced'>
python some_python_function () {
d.setVar("TEXT", "Hello World")
print d.getVar("TEXT")
print d.getVar("TEXT", True)
}
</literallayout>
Because the Python "bb" and "os" modules are already
@@ -1258,7 +1180,7 @@
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>.
function, use <filename>d.getVar("X", True)</filename>.
Or, for more complicated expressions, use
<filename>d.expand()</filename>.
</note>
@@ -1310,7 +1232,7 @@
Here is an example:
<literallayout class='monospaced'>
def get_depends(d):
if d.getVar('SOMECONDITION'):
if d.getVar('SOMECONDITION', True):
return "dependencywithcond"
else:
return "dependency"
@@ -1445,7 +1367,7 @@
based on the value of another variable:
<literallayout class='monospaced'>
python () {
if d.getVar('SOMEVAR') == 'value':
if d.getVar('SOMEVAR', True) == 'value':
d.setVar('ANOTHERVAR', 'value2')
}
</literallayout>
@@ -2020,196 +1942,128 @@
<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.
BitBake allows installation of event handlers within
recipe and class files.
Events are triggered at certain points during operation,
such as the beginning of an operation against a given recipe
(<filename>*.bb</filename> file), the start of a given task,
task failure, task success, and so forth.
The intent is to make it easy to do things like email
notification on build failures.
notification on build failure.
</para>
<para>
Following is an example event handler that prints the name
of the event and the content of the
<filename>FILE</filename> variable:
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
from bb import data
print("The name of the Event is %s" % getName(e))
print("The file we run for is %s" % d.getVar('FILE'))
print("The file we run for is %s" % data.getVar('FILE', e.data, True))
}
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
This event handler gets called every time an event is
triggered.
A global variable "<filename>e</filename>" is defined and
"<filename>e.data</filename>" contains an instance of
"<filename>bb.data</filename>".
With the <filename>getName(e)</filename> method, one 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.
Because you probably are only interested in a subset of events,
you would likely use the <filename>[eventmask]</filename> flag
for your event handler to be sure that only certain events
trigger the handler.
Given the previous example, suppose you only wanted the
<filename>bb.build.TaskFailed</filename> event to trigger that
event handler.
Use the flag as follows:
<literallayout class='monospaced'>
addhandler myclass_eventhandler
myclass_eventhandler[eventmask] = "bb.build.TaskFailed"
python myclass_eventhandler() {
from bb.event import getName
from bb import data
print("The name of the Event is %s" % getName(e))
print("The file we run for is %s" % data.getVar('FILE', e.data, True))
}
</literallayout>
</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:
During a standard build, the following common events might occur:
<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_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.
<filename>bb.event.ConfigParsed()</filename>
</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.
<filename>bb.event.ParseStarted()</filename>
</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.
<filename>bb.event.ParseProgress()</filename>
</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.
<filename>bb.event.ParseCompleted()</filename>
</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.
<filename>bb.event.BuildStarted()</filename>
</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.
<filename>bb.build.TaskStarted()</filename>
</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.
<filename>bb.build.TaskInvalid()</filename>
</para></listitem>
<listitem><para>
<filename>bb.build.TaskInvalid()</filename>:
Fired if BitBake tries to execute a task that does not exist.
<filename>bb.build.TaskFailedSilent()</filename>
</para></listitem>
<listitem><para>
<filename>bb.build.TaskFailedSilent()</filename>:
Fired for setscene tasks that fail and should not be
presented to the user verbosely.
<filename>bb.build.TaskFailed()</filename>
</para></listitem>
<listitem><para>
<filename>bb.build.TaskFailed()</filename>:
Fired for normal tasks that fail.
<filename>bb.build.TaskSucceeded()</filename>
</para></listitem>
<listitem><para>
<filename>bb.build.TaskSucceeded()</filename>:
Fired when a task successfully completes.
<filename>bb.event.BuildCompleted()</filename>
</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.
<filename>bb.cooker.CookerExit()</filename>
</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:
Here is a list of other events that occur based on specific requests
to the server:
<itemizedlist>
<listitem><para>
<filename>bb.event.TreeDataPreparationStarted()</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.TreeDataPreparationProgress()</filename>
<filename>bb.event.TreeDataPreparationProgress</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.TreeDataPreparationCompleted()</filename>
<filename>bb.event.TreeDataPreparationCompleted</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.DepTreeGenerated()</filename>
<filename>bb.event.DepTreeGenerated</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.CoreBaseFilesFound()</filename>
<filename>bb.event.CoreBaseFilesFound</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.ConfigFilePathFound()</filename>
<filename>bb.event.ConfigFilePathFound</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.FilesMatchingFound()</filename>
<filename>bb.event.FilesMatchingFound</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.ConfigFilesFound()</filename>
<filename>bb.event.ConfigFilesFound</filename>
</para></listitem>
<listitem><para>
<filename>bb.event.TargetsTreeGenerated()</filename>
<filename>bb.event.TargetsTreeGenerated</filename>
</para></listitem>
</itemizedlist>
</para>
@@ -2652,70 +2506,47 @@
</para>
<para>
These checksums are stored in
<link linkend='var-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:
This list is a place holder of content existed from previous work
on the manual.
Some or all of it probably needs integrated into the subsections
that make up this section.
For now, I have just provided a short glossary-like description
for each variable.
Ultimately, this list goes away.
<itemizedlist>
<listitem><para>
<link linkend='var-BB_HASHCHECK_FUNCTION'><filename>BB_HASHCHECK_FUNCTION</filename></link>:
<listitem><para><filename>STAMP</filename>:
The base path to create stamp files.</para></listitem>
<listitem><para><filename>STAMPCLEAN</filename>
Again, the base path to create stamp files but can use wildcards
for matching a range of files for clean operations.
</para></listitem>
<listitem><para><filename>BB_STAMP_WHITELIST</filename>
Lists stamp files that are looked at when the stamp policy
is "whitelist".
</para></listitem>
<listitem><para><filename>BB_STAMP_POLICY</filename>
Defines the mode for comparing timestamps of stamp files.
</para></listitem>
<listitem><para><filename>BB_HASHCHECK_FUNCTION</filename>
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_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_SETSCENE_VERIFY_FUNCTION2'><filename>BB_SETSCENE_VERIFY_FUNCTION2</filename></link>:
<listitem><para><filename>BB_SETSCENE_VERIFY_FUNCTION2</filename>
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_STAMP_POLICY'><filename>BB_STAMP_POLICY</filename></link>:
Defines the mode for comparing timestamps of stamp files.
<listitem><para><filename>BB_SETSCENE_DEPVALID</filename>
Specifies a function BitBake calls that determines
whether BitBake requires a setscene dependency to
be met.
</para></listitem>
<listitem><para>
<link linkend='var-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_TASKHASH'><filename>BB_TASKHASH</filename></link>:
<listitem><para><filename>BB_TASKHASH</filename>
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-STAMP'><filename>STAMP</filename></link>:
The base path to create stamp files.
</para></listitem>
<listitem><para>
<link linkend='var-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>

View File

@@ -78,7 +78,7 @@
</para>
<para>
In OpenEmbedded-Core, <filename>ASSUME_PROVIDED</filename>
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
@@ -964,7 +964,7 @@
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
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
@@ -980,7 +980,7 @@
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
The "native" variants are from the OpenEmbedded Core
metadata:
<literallayout class='monospaced'>
BBCLASSEXTEND =+ "native nativesdk"
@@ -1143,6 +1143,8 @@
<glossdef>
<para>
Sets the base location where layers are stored.
By default, this location is set to
<filename>${COREBASE}</filename>.
This setting is used in conjunction with
<filename>bitbake-layers layerindex-fetch</filename> and
tells <filename>bitbake-layers</filename> where to place
@@ -1537,6 +1539,24 @@
</glossdef>
</glossentry>
<glossentry id='var-FILESDIR'><glossterm>FILESDIR</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 if the file
was not found using
<link linkend='var-FILESPATH'><filename>FILESPATH</filename></link>.
<note>
The <filename>FILESDIR</filename> variable is
deprecated and you should use
<filename>FILESPATH</filename> in all new code.
</note>
</para>
</glossdef>
</glossentry>
<glossentry id='var-FILESPATH'><glossterm>FILESPATH</glossterm>
<glossdef>
<para>
@@ -1594,19 +1614,9 @@
<glossentry id='var-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.
Causes the named class to be inherited at
this point during parsing.
The variable is only valid in configuration files.
</para>
</glossdef>
</glossentry>
@@ -1901,7 +1911,7 @@
Here are two examples:
<literallayout class='monospaced'>
PREFERRED_VERSION_python = "2.7.3"
PREFERRED_VERSION_linux-yocto = "4.12%"
PREFERRED_VERSION_linux-yocto = "3.10%"
</literallayout>
</para>
</glossdef>
@@ -2089,16 +2099,6 @@
</glossdef>
</glossentry>
<glossentry id='var-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-RPROVIDES'><glossterm>RPROVIDES</glossterm>
<glossdef>
<para>

View File

@@ -56,7 +56,7 @@
-->
<copyright>
<year>2004-2018</year>
<year>2004-2016</year>
<holder>Richard Purdie</holder>
<holder>Chris Larson</holder>
<holder>and Phil Blundell</holder>

View File

@@ -105,7 +105,7 @@ Show debug logging for the specified logging domains
profile the command and print a report
.TP
.B \-uUI, \-\-ui=UI
User interface to use. Currently, knotty, taskexp or ncurses can be specified as UI.
User interface to use. Currently, hob, depexp, goggle or ncurses can be specified as UI.
.TP
.B \-tSERVERTYPE, \-\-servertype=SERVERTYPE
Choose which server to use, none, process or xmlrpc.

View File

@@ -3,7 +3,7 @@
#
# This is a copy on write dictionary and set which abuses classes to try and be nice and fast.
#
# Copyright (C) 2006 Tim Ansell
# Copyright (C) 2006 Tim Amsell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -213,11 +213,11 @@ if __name__ == "__main__":
print()
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)
for x in b.iteritems():
for x in b.items():
print(x)
print()
@@ -225,11 +225,11 @@ if __name__ == "__main__":
b['a'] = 'c'
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)
for x in b.iteritems():
for x in b.items():
print(x)
print()
@@ -244,22 +244,22 @@ if __name__ == "__main__":
a['set'].add("o2")
print("a", a)
for x in a['set'].itervalues():
for x in a['set'].values():
print(x)
print("--")
print("b", b)
for x in b['set'].itervalues():
for x in b['set'].values():
print(x)
print()
b['set'].add('o3')
print("a", a)
for x in a['set'].itervalues():
for x in a['set'].values():
print(x)
print("--")
print("b", b)
for x in b['set'].itervalues():
for x in b['set'].values():
print(x)
print()
@@ -269,7 +269,7 @@ if __name__ == "__main__":
a['set2'].add("o2")
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)
@@ -289,7 +289,7 @@ if __name__ == "__main__":
print("Yay - has_key with delete works!")
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)
@@ -300,7 +300,7 @@ if __name__ == "__main__":
b.__revertitem__('b')
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)
@@ -310,7 +310,7 @@ if __name__ == "__main__":
b.__revertitem__('dict')
print("a", a)
for x in a.iteritems():
for x in a.items():
print(x)
print("--")
print("b", b)

View File

@@ -21,7 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
__version__ = "1.38.0"
__version__ = "1.32.0"
import sys
if sys.version_info < (3, 4, 0):

View File

@@ -91,14 +91,14 @@ class TaskBase(event.Event):
def __init__(self, t, logfile, d):
self._task = t
self._package = d.getVar("PF")
self._mc = d.getVar("BB_CURRENT_MC")
self.taskfile = d.getVar("FILE")
self._package = d.getVar("PF", True)
self._mc = d.getVar("BB_CURRENT_MC", True)
self.taskfile = d.getVar("FILE", True)
self.taskname = self._task
self.logfile = logfile
self.time = time.time()
event.Event.__init__(self)
self._message = "recipe %s: task %s: %s" % (d.getVar("PF"), t, self.getDisplayName())
self._message = "recipe %s: task %s: %s" % (d.getVar("PF", True), t, self.getDisplayName())
def getTask(self):
return self._task
@@ -195,13 +195,13 @@ def exec_func(func, d, dirs = None, pythonexception=False):
oldcwd = None
flags = d.getVarFlags(func)
cleandirs = flags.get('cleandirs') if flags else None
cleandirs = flags.get('cleandirs')
if cleandirs:
for cdir in d.expand(cleandirs).split():
bb.utils.remove(cdir, True)
bb.utils.mkdirhier(cdir)
if flags and dirs is None:
if dirs is None:
dirs = flags.get('dirs')
if dirs:
dirs = d.expand(dirs).split()
@@ -227,17 +227,17 @@ def exec_func(func, d, dirs = None, pythonexception=False):
else:
lockfiles = None
tempdir = d.getVar('T')
tempdir = d.getVar('T', True)
# or func allows items to be executed outside of the normal
# task set, such as buildhistory
task = d.getVar('BB_RUNTASK') or func
task = d.getVar('BB_RUNTASK', True) or func
if task == func:
taskfunc = task
else:
taskfunc = "%s.%s" % (task, func)
runfmt = d.getVar('BB_RUNFMT') or "run.{func}.{pid}"
runfmt = d.getVar('BB_RUNFMT', True) or "run.{func}.{pid}"
runfn = runfmt.format(taskfunc=taskfunc, task=task, func=func, pid=os.getpid())
runfile = os.path.join(tempdir, runfn)
bb.utils.mkdirhier(os.path.dirname(runfile))
@@ -369,7 +369,7 @@ exit $ret
cmd = runfile
if d.getVarFlag(func, 'fakeroot', False):
fakerootcmd = d.getVar('FAKEROOT')
fakerootcmd = d.getVar('FAKEROOT', True)
if fakerootcmd:
cmd = [fakerootcmd, runfile]
@@ -378,7 +378,7 @@ exit $ret
else:
logfile = sys.stdout
progress = d.getVarFlag(func, 'progress')
progress = d.getVarFlag(func, 'progress', True)
if progress:
if progress == 'percent':
# Use default regex
@@ -430,7 +430,7 @@ exit $ret
else:
break
tempdir = d.getVar('T')
tempdir = d.getVar('T', True)
fifopath = os.path.join(tempdir, 'fifo.%s' % os.getpid())
if os.path.exists(fifopath):
os.unlink(fifopath)
@@ -443,7 +443,7 @@ exit $ret
with open(os.devnull, 'r+') as stdin:
bb.process.run(cmd, shell=False, stdin=stdin, log=logfile, extrafiles=[(fifo,readfifo)])
except bb.process.CmdError:
logfn = d.getVar('BB_LOGFILE')
logfn = d.getVar('BB_LOGFILE', True)
raise FuncFailed(func, logfn)
finally:
os.unlink(fifopath)
@@ -474,18 +474,18 @@ def _exec_task(fn, task, d, quieterr):
logger.debug(1, "Executing task %s", task)
localdata = _task_data(fn, task, d)
tempdir = localdata.getVar('T')
tempdir = localdata.getVar('T', True)
if not tempdir:
bb.fatal("T variable not set, unable to build")
# Change nice level if we're asked to
nice = localdata.getVar("BB_TASK_NICE_LEVEL")
nice = localdata.getVar("BB_TASK_NICE_LEVEL", True)
if nice:
curnice = os.nice(0)
nice = int(nice) - curnice
newnice = os.nice(nice)
logger.debug(1, "Renice to %s " % newnice)
ionice = localdata.getVar("BB_TASK_IONICE_LEVEL")
ionice = localdata.getVar("BB_TASK_IONICE_LEVEL", True)
if ionice:
try:
cls, prio = ionice.split(".", 1)
@@ -496,7 +496,7 @@ def _exec_task(fn, task, d, quieterr):
bb.utils.mkdirhier(tempdir)
# Determine the logfile to generate
logfmt = localdata.getVar('BB_LOGFMT') or 'log.{task}.{pid}'
logfmt = localdata.getVar('BB_LOGFMT', True) or 'log.{task}.{pid}'
logbase = logfmt.format(task=task, pid=os.getpid())
# Document the order of the tasks...
@@ -563,7 +563,6 @@ def _exec_task(fn, task, d, quieterr):
localdata.setVar('BB_LOGFILE', logfn)
localdata.setVar('BB_RUNTASK', task)
localdata.setVar('BB_TASK_LOGGER', bblogger)
flags = localdata.getVarFlags(task)
@@ -629,7 +628,7 @@ def exec_task(fn, task, d, profile = False):
quieterr = True
if profile:
profname = "profile-%s.log" % (d.getVar("PN") + "-" + task)
profname = "profile-%s.log" % (d.getVar("PN", True) + "-" + task)
try:
import cProfile as profile
except:
@@ -669,9 +668,9 @@ def stamp_internal(taskname, d, file_name, baseonly=False, noextra=False):
stamp = d.stamp[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
stamp = d.getVar('STAMP')
file_name = d.getVar('BB_FILENAME')
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info') or ""
stamp = d.getVar('STAMP', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
if baseonly:
return stamp
@@ -705,9 +704,9 @@ def stamp_cleanmask_internal(taskname, d, file_name):
stamp = d.stampclean[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
stamp = d.getVar('STAMPCLEAN')
file_name = d.getVar('BB_FILENAME')
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info') or ""
stamp = d.getVar('STAMPCLEAN', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
if not stamp:
return []
@@ -743,7 +742,7 @@ def make_stamp(task, d, file_name = None):
# as it completes
if not task.endswith("_setscene") and task != "do_setscene" and not file_name:
stampbase = stamp_internal(task, d, None, True)
file_name = d.getVar('BB_FILENAME')
file_name = d.getVar('BB_FILENAME', True)
bb.parse.siggen.dump_sigtask(file_name, task, stampbase, True)
def del_stamp(task, d, file_name = None):
@@ -765,7 +764,7 @@ def write_taint(task, d, file_name = None):
if file_name:
taintfn = d.stamp[file_name] + '.' + task + '.taint'
else:
taintfn = d.getVar('STAMP') + '.' + task + '.taint'
taintfn = d.getVar('STAMP', True) + '.' + task + '.taint'
bb.utils.mkdirhier(os.path.dirname(taintfn))
# The specific content of the taint file is not really important,
# we just need it to be random, so a random UUID is used
@@ -862,52 +861,3 @@ def deltask(task, d):
if task in deps:
deps.remove(task)
d.setVarFlag(bbtask, 'deps', deps)
def preceedtask(task, with_recrdeptasks, d):
"""
Returns a set of tasks in the current recipe which were specified as
precondition by the task itself ("after") or which listed themselves
as precondition ("before"). Preceeding tasks specified via the
"recrdeptask" are included in the result only if requested. Beware
that this may lead to the task itself being listed.
"""
preceed = set()
# Ignore tasks which don't exist
tasks = d.getVar('__BBTASKS', False)
if task not in tasks:
return preceed
preceed.update(d.getVarFlag(task, 'deps') or [])
if with_recrdeptasks:
recrdeptask = d.getVarFlag(task, 'recrdeptask')
if recrdeptask:
preceed.update(recrdeptask.split())
return preceed
def tasksbetween(task_start, task_end, d):
"""
Return the list of tasks between two tasks in the current recipe,
where task_start is to start at and task_end is the task to end at
(and task_end has a dependency chain back to task_start).
"""
outtasks = []
tasks = list(filter(lambda k: d.getVarFlag(k, "task"), d.keys()))
def follow_chain(task, endtask, chain=None):
if not chain:
chain = []
chain.append(task)
for othertask in tasks:
if othertask == task:
continue
if task == endtask:
for ctask in chain:
if ctask not in outtasks:
outtasks.append(ctask)
else:
deps = d.getVarFlag(othertask, 'deps', False)
if task in deps:
follow_chain(othertask, endtask, chain)
chain.pop()
follow_chain(task_start, task_end)
return outtasks

View File

@@ -37,7 +37,7 @@ import bb.utils
logger = logging.getLogger("BitBake.Cache")
__cache_version__ = "151"
__cache_version__ = "150"
def getCacheFile(path, filename, data_hash):
return os.path.join(path, filename + "." + data_hash)
@@ -71,7 +71,7 @@ class RecipeInfoCommon(object):
@classmethod
def flaglist(cls, flag, varlist, metadata, squash=False):
out_dict = dict((var, metadata.getVarFlag(var, flag))
out_dict = dict((var, metadata.getVarFlag(var, flag, True))
for var in varlist)
if squash:
return dict((k,v) for (k,v) in out_dict.items() if v)
@@ -86,9 +86,9 @@ class RecipeInfoCommon(object):
class CoreRecipeInfo(RecipeInfoCommon):
__slots__ = ()
cachefile = "bb_cache.dat"
cachefile = "bb_cache.dat"
def __init__(self, filename, metadata):
def __init__(self, filename, metadata):
self.file_depends = metadata.getVar('__depends', False)
self.timestamp = bb.parse.cached_mtime(filename)
self.variants = self.listvar('__VARIANTS', metadata) + ['']
@@ -107,7 +107,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.pn = self.getvar('PN', metadata)
self.packages = self.listvar('PACKAGES', metadata)
if not self.packages:
if not self.pn in self.packages:
self.packages.append(self.pn)
self.basetaskhashes = self.taskvar('BB_BASEHASH', self.tasks, metadata)
@@ -122,7 +122,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.defaultpref = self.intvar('DEFAULT_PREFERENCE', metadata)
self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata)
self.stamp = self.getvar('STAMP', metadata)
self.stampclean = self.getvar('STAMPCLEAN', metadata)
self.stampclean = self.getvar('STAMPCLEAN', metadata)
self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata)
self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True)
self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
@@ -217,7 +217,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.packages_dynamic[package].append(fn)
# Build hash of runtime depends and recommends
for package in self.packages:
for package in self.packages + [self.pn]:
cachedata.rundeps[fn][package] = list(self.rdepends) + self.rdepends_pkg[package]
cachedata.runrecs[fn][package] = list(self.rrecommends) + self.rrecommends_pkg[package]
@@ -296,7 +296,7 @@ def parse_recipe(bb_data, bbfile, appends, mc=''):
bb_data.setVar("__BBMULTICONFIG", mc)
# expand tmpdir to include this topdir
bb_data.setVar('TMPDIR', bb_data.getVar('TMPDIR') or "")
bb_data.setVar('TMPDIR', bb_data.getVar('TMPDIR', True) or "")
bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
oldpath = os.path.abspath(os.getcwd())
bb.parse.cached_mtime_noerror(bbfile_loc)
@@ -375,10 +375,10 @@ class Cache(NoCache):
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
# It will be used later for deciding whether we
# need extra cache file dump/load support
self.caches_array = caches_array
self.cachedir = data.getVar("CACHE")
self.cachedir = data.getVar("CACHE", True)
self.clean = set()
self.checked = set()
self.depends_cache = {}
@@ -395,7 +395,7 @@ class Cache(NoCache):
self.has_cache = True
self.cachefile = getCacheFile(self.cachedir, "bb_cache.dat", self.data_hash)
logger.debug(1, "Cache dir: %s", self.cachedir)
logger.debug(1, "Using cache in '%s'", self.cachedir)
bb.utils.mkdirhier(self.cachedir)
cache_ok = True
@@ -408,8 +408,6 @@ class Cache(NoCache):
self.load_cachefile()
elif os.path.isfile(self.cachefile):
logger.info("Out of date cache found, rebuilding...")
else:
logger.debug(1, "Cache file %s not found, building..." % self.cachefile)
def load_cachefile(self):
cachesize = 0
@@ -423,10 +421,9 @@ class Cache(NoCache):
cachesize += os.fstat(cachefile.fileno()).st_size
bb.event.fire(bb.event.CacheLoadStarted(cachesize), self.data)
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)
with open(cachefile, "rb") as cachefile:
pickled = pickle.Unpickler(cachefile)
# Check cache version information
@@ -441,8 +438,8 @@ class Cache(NoCache):
logger.info('Cache version mismatch, rebuilding...')
return
elif bitbake_ver != bb.__version__:
logger.info('Bitbake version mismatch, rebuilding...')
return
logger.info('Bitbake version mismatch, rebuilding...')
return
# Load the rest of the cache file
current_progress = 0
@@ -465,10 +462,6 @@ 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
@@ -619,13 +612,13 @@ class Cache(NoCache):
a = fl.find(":True")
b = fl.find(":False")
if ((a < 0) and b) or ((b > 0) and (b < a)):
f = fl[:b+6]
fl = fl[b+7:]
f = fl[:b+6]
fl = fl[b+7:]
elif ((b < 0) and a) or ((a > 0) and (a < b)):
f = fl[:a+5]
fl = fl[a+6:]
f = fl[:a+5]
fl = fl[a+6:]
else:
break
break
fl = fl.strip()
if "*" in f:
continue
@@ -799,8 +792,8 @@ class MultiProcessCache(object):
self.cachedata_extras = self.create_cachedata()
def init_cache(self, d, cache_file_name=None):
cachedir = (d.getVar("PERSISTENT_DIR") or
d.getVar("CACHE"))
cachedir = (d.getVar("PERSISTENT_DIR", True) or
d.getVar("CACHE", True))
if cachedir in [None, '']:
return
bb.utils.mkdirhier(cachedir)
@@ -889,3 +882,4 @@ class MultiProcessCache(object):
p.dump([data, self.__class__.CACHE_VERSION])
bb.utils.unlockfile(glf)

View File

@@ -1,22 +1,3 @@
"""
BitBake code parser
Parses actual code (i.e. python and shell) for functions and in-line
expressions. Used mainly to determine dependencies on other functions
and variables within the BitBake metadata. Also provides a cache for
this information in order to speed up processing.
(Not to be confused with the code that parses the metadata itself,
see lib/bb/parse/ for that).
NOTE: if you change how the parsers gather information you will almost
certainly need to increment CodeParserCache.CACHE_VERSION below so that
any existing codeparser cache gets invalidated. Additionally you'll need
to increment __cache_version__ in cache.py in order to ensure that old
recipe caches don't trigger "Taskhash mismatch" errors.
"""
import ast
import sys
import codegen
@@ -136,11 +117,7 @@ class shellCacheLine(object):
class CodeParserCache(MultiProcessCache):
cache_file_name = "bb_codeparser.dat"
# NOTE: you must increment this if you change how the parsers gather information,
# so that an existing cache gets invalidated. Additionally you'll need
# to increment __cache_version__ in cache.py in order to ensure that old
# recipe caches don't trigger "Taskhash mismatch" errors.
CACHE_VERSION = 9
CACHE_VERSION = 8
def __init__(self):
MultiProcessCache.__init__(self)
@@ -209,15 +186,13 @@ class BufferedLogger(Logger):
def flush(self):
for record in self.buffer:
if self.target.isEnabledFor(record.levelno):
self.target.handle(record)
self.target.handle(record)
self.buffer = []
class PythonParser():
getvars = (".getVar", ".appendVar", ".prependVar")
getvarflags = (".getVarFlag", ".appendVarFlag", ".prependVarFlag")
containsfuncs = ("bb.utils.contains", "base_contains")
containsanyfuncs = ("bb.utils.contains_any", "bb.utils.filter")
containsfuncs = ("bb.utils.contains", "base_contains", "bb.utils.contains_any")
execfuncs = ("bb.build.exec_func", "bb.build.exec_task")
def warn(self, func, arg):
@@ -236,17 +211,13 @@ class PythonParser():
def visit_Call(self, node):
name = self.called_node_name(node.func)
if name and (name.endswith(self.getvars) or name.endswith(self.getvarflags) or name in self.containsfuncs or name in self.containsanyfuncs):
if name and (name.endswith(self.getvars) or name.endswith(self.getvarflags) or name in self.containsfuncs):
if isinstance(node.args[0], ast.Str):
varname = node.args[0].s
if name in self.containsfuncs and isinstance(node.args[1], ast.Str):
if varname not in self.contains:
self.contains[varname] = set()
self.contains[varname].add(node.args[1].s)
elif name in self.containsanyfuncs and isinstance(node.args[1], ast.Str):
if varname not in self.contains:
self.contains[varname] = set()
self.contains[varname].update(node.args[1].s.split())
elif name.endswith(self.getvarflags):
if isinstance(node.args[1], ast.Str):
self.references.add('%s[%s]' % (varname, node.args[1].s))
@@ -371,7 +342,8 @@ class ShellParser():
except pyshlex.NeedMore:
raise sherrors.ShellSyntaxError("Unexpected EOF")
self.process_tokens(tokens)
for token in tokens:
self.process_tokens(token)
def process_tokens(self, tokens):
"""Process a supplied portion of the syntax tree as returned by
@@ -417,24 +389,18 @@ class ShellParser():
"case_clause": case_clause,
}
def process_token_list(tokens):
for token in tokens:
if isinstance(token, list):
process_token_list(token)
continue
name, value = token
try:
more_tokens, words = token_handlers[name](value)
except KeyError:
raise NotImplementedError("Unsupported token type " + name)
for token in tokens:
name, value = token
try:
more_tokens, words = token_handlers[name](value)
except KeyError:
raise NotImplementedError("Unsupported token type " + name)
if more_tokens:
self.process_tokens(more_tokens)
if more_tokens:
self.process_tokens(more_tokens)
if words:
self.process_words(words)
process_token_list(tokens)
if words:
self.process_words(words)
def process_words(self, words):
"""Process a set of 'words' in pyshyacc parlance, which includes

View File

@@ -28,15 +28,8 @@ and must not trigger events, directly or indirectly.
Commands are queued in a CommandQueue
"""
from collections import OrderedDict, defaultdict
import bb.event
import bb.cooker
import bb.remotedata
class DataStoreConnectionHandle(object):
def __init__(self, dsindex=0):
self.dsindex = dsindex
class CommandCompleted(bb.event.Event):
pass
@@ -50,8 +43,6 @@ class CommandFailed(CommandExit):
def __init__(self, message):
self.error = message
CommandExit.__init__(self, 1)
def __str__(self):
return "Command execution failed: %s" % self.error
class CommandError(Exception):
pass
@@ -64,7 +55,6 @@ class Command:
self.cooker = cooker
self.cmds_sync = CommandsSync()
self.cmds_async = CommandsAsync()
self.remotedatastores = bb.remotedata.RemoteDatastores(cooker)
# FIXME Add lock for this
self.currentAsyncCommand = None
@@ -78,8 +68,7 @@ class Command:
if not hasattr(command_method, 'readonly') or False == getattr(command_method, 'readonly'):
return None, "Not able to execute not readonly commands in readonly mode"
try:
self.cooker.process_inotify_updates()
if getattr(command_method, 'needconfig', True):
if getattr(command_method, 'needconfig', False):
self.cooker.updateCacheSync()
result = command_method(self, commandline)
except CommandError as exc:
@@ -99,7 +88,6 @@ class Command:
def runAsyncCommand(self):
try:
self.cooker.process_inotify_updates()
if self.cooker.state in (bb.cooker.state.error, bb.cooker.state.shutdown, bb.cooker.state.forceshutdown):
# updateCache will trigger a shutdown of the parser
# and then raise BBHandledException triggering an exit
@@ -137,23 +125,14 @@ class Command:
def finishAsyncCommand(self, msg=None, code=None):
if msg or msg == "":
bb.event.fire(CommandFailed(msg), self.cooker.data)
bb.event.fire(CommandFailed(msg), self.cooker.expanded_data)
elif code:
bb.event.fire(CommandExit(code), self.cooker.data)
bb.event.fire(CommandExit(code), self.cooker.expanded_data)
else:
bb.event.fire(CommandCompleted(), self.cooker.data)
bb.event.fire(CommandCompleted(), self.cooker.expanded_data)
self.currentAsyncCommand = None
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)
class CommandsSync:
"""
A class of synchronous commands
@@ -200,7 +179,6 @@ class CommandsSync:
"""
varname = params[0]
value = str(params[1])
command.cooker.extraconfigdata[varname] = value
command.cooker.data.setVar(varname, value)
def getSetVariable(self, command, params):
@@ -240,15 +218,59 @@ class CommandsSync:
command.cooker.configuration.postfile = postfiles
setPrePostConfFiles.needconfig = False
def getCpuCount(self, command, params):
"""
Get the CPU count on the bitbake server
"""
return bb.utils.cpu_count()
getCpuCount.readonly = True
getCpuCount.needconfig = False
def matchFile(self, command, params):
fMatch = params[0]
return command.cooker.matchFile(fMatch)
matchFile.needconfig = False
def getUIHandlerNum(self, command, params):
return bb.event.get_uihandler()
getUIHandlerNum.needconfig = False
getUIHandlerNum.readonly = True
def generateNewImage(self, command, params):
image = params[0]
base_image = params[1]
package_queue = params[2]
timestamp = params[3]
description = params[4]
return command.cooker.generateNewImage(image, base_image,
package_queue, timestamp, description)
def ensureDir(self, command, params):
directory = params[0]
bb.utils.mkdirhier(directory)
ensureDir.needconfig = False
def setVarFile(self, command, params):
"""
Save a variable in a file; used for saving in a configuration file
"""
var = params[0]
val = params[1]
default_file = params[2]
op = params[3]
command.cooker.modifyConfigurationVar(var, val, default_file, op)
setVarFile.needconfig = False
def removeVarFile(self, command, params):
"""
Remove a variable declaration from a file
"""
var = params[0]
command.cooker.removeConfigurationVar(var)
removeVarFile.needconfig = False
def createConfigFile(self, command, params):
"""
Create an extra configuration file
"""
name = params[0]
command.cooker.createConfigFile(name)
createConfigFile.needconfig = False
def setEventMask(self, command, params):
handlerNum = params[0]
@@ -273,307 +295,9 @@ class CommandsSync:
def updateConfig(self, command, params):
options = params[0]
environment = params[1]
cmdline = params[2]
command.cooker.updateConfigOpts(options, environment, cmdline)
command.cooker.updateConfigOpts(options, environment)
updateConfig.needconfig = False
def parseConfiguration(self, command, params):
"""Instruct bitbake to parse its configuration
NOTE: it is only necessary to call this if you aren't calling any normal action
(otherwise parsing is taken care of automatically)
"""
command.cooker.parseConfiguration()
parseConfiguration.needconfig = False
def getLayerPriorities(self, command, params):
command.cooker.parseConfiguration()
ret = []
# regex objects cannot be marshalled by xmlrpc
for collection, pattern, regex, pri in command.cooker.bbfile_config_priorities:
ret.append((collection, pattern, regex.pattern, pri))
return ret
getLayerPriorities.readonly = True
def getRecipes(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(command.cooker.recipecaches[mc].pkg_pn.items())
getRecipes.readonly = True
def getRecipeDepends(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(command.cooker.recipecaches[mc].deps.items())
getRecipeDepends.readonly = True
def getRecipeVersions(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].pkg_pepvpr
getRecipeVersions.readonly = True
def getRecipeProvides(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].fn_provides
getRecipeProvides.readonly = True
def getRecipePackages(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].packages
getRecipePackages.readonly = True
def getRecipePackagesDynamic(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].packages_dynamic
getRecipePackagesDynamic.readonly = True
def getRProviders(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].rproviders
getRProviders.readonly = True
def getRuntimeDepends(self, command, params):
ret = []
try:
mc = params[0]
except IndexError:
mc = ''
rundeps = command.cooker.recipecaches[mc].rundeps
for key, value in rundeps.items():
if isinstance(value, defaultdict):
value = dict(value)
ret.append((key, value))
return ret
getRuntimeDepends.readonly = True
def getRuntimeRecommends(self, command, params):
ret = []
try:
mc = params[0]
except IndexError:
mc = ''
runrecs = command.cooker.recipecaches[mc].runrecs
for key, value in runrecs.items():
if isinstance(value, defaultdict):
value = dict(value)
ret.append((key, value))
return ret
getRuntimeRecommends.readonly = True
def getRecipeInherits(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].inherits
getRecipeInherits.readonly = True
def getBbFilePriority(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].bbfile_priority
getBbFilePriority.readonly = True
def getDefaultPreference(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return command.cooker.recipecaches[mc].pkg_dp
getDefaultPreference.readonly = True
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])))
return list(skipdict.items())
getSkippedRecipes.readonly = True
def getOverlayedRecipes(self, command, params):
return list(command.cooker.collection.overlayed.items())
getOverlayedRecipes.readonly = True
def getFileAppends(self, command, params):
fn = params[0]
return command.cooker.collection.get_file_appends(fn)
getFileAppends.readonly = True
def getAllAppends(self, command, params):
return command.cooker.collection.bbappends
getAllAppends.readonly = True
def findProviders(self, command, params):
return command.cooker.findProviders()
findProviders.readonly = True
def findBestProvider(self, command, params):
(mc, pn) = split_mc_pn(params[0])
return command.cooker.findBestProvider(pn, mc)
findBestProvider.readonly = True
def allProviders(self, command, params):
try:
mc = params[0]
except IndexError:
mc = ''
return list(bb.providers.allProviders(command.cooker.recipecaches[mc]).items())
allProviders.readonly = True
def getRuntimeProviders(self, command, params):
rprovide = params[0]
try:
mc = params[1]
except IndexError:
mc = ''
all_p = bb.providers.getRuntimeProviders(command.cooker.recipecaches[mc], rprovide)
if all_p:
best = bb.providers.filterProvidersRunTime(all_p, rprovide,
command.cooker.data,
command.cooker.recipecaches[mc])[0][0]
else:
best = None
return all_p, best
getRuntimeProviders.readonly = True
def dataStoreConnectorFindVar(self, command, params):
dsindex = params[0]
name = params[1]
datastore = command.remotedatastores[dsindex]
value, overridedata = datastore._findVar(name)
if value:
content = value.get('_content', None)
if isinstance(content, bb.data_smart.DataSmart):
# Value is a datastore (e.g. BB_ORIGENV) - need to handle this carefully
idx = command.remotedatastores.check_store(content, True)
return {'_content': DataStoreConnectionHandle(idx),
'_connector_origtype': 'DataStoreConnectionHandle',
'_connector_overrides': overridedata}
elif isinstance(content, set):
return {'_content': list(content),
'_connector_origtype': 'set',
'_connector_overrides': overridedata}
else:
value['_connector_overrides'] = overridedata
else:
value = {}
value['_connector_overrides'] = overridedata
return value
dataStoreConnectorFindVar.readonly = True
def dataStoreConnectorGetKeys(self, command, params):
dsindex = params[0]
datastore = command.remotedatastores[dsindex]
return list(datastore.keys())
dataStoreConnectorGetKeys.readonly = True
def dataStoreConnectorGetVarHistory(self, command, params):
dsindex = params[0]
name = params[1]
datastore = command.remotedatastores[dsindex]
return datastore.varhistory.variable(name)
dataStoreConnectorGetVarHistory.readonly = True
def dataStoreConnectorExpandPythonRef(self, command, params):
config_data_dict = params[0]
varname = params[1]
expr = params[2]
config_data = command.remotedatastores.receive_datastore(config_data_dict)
varparse = bb.data_smart.VariableParse(varname, config_data)
return varparse.python_sub(expr)
def dataStoreConnectorRelease(self, command, params):
dsindex = params[0]
if dsindex <= 0:
raise CommandError('dataStoreConnectorRelease: invalid index %d' % dsindex)
command.remotedatastores.release(dsindex)
def dataStoreConnectorSetVarFlag(self, command, params):
dsindex = params[0]
name = params[1]
flag = params[2]
value = params[3]
datastore = command.remotedatastores[dsindex]
datastore.setVarFlag(name, flag, value)
def dataStoreConnectorDelVar(self, command, params):
dsindex = params[0]
name = params[1]
datastore = command.remotedatastores[dsindex]
if len(params) > 2:
flag = params[2]
datastore.delVarFlag(name, flag)
else:
datastore.delVar(name)
def dataStoreConnectorRenameVar(self, command, params):
dsindex = params[0]
name = params[1]
newname = params[2]
datastore = command.remotedatastores[dsindex]
datastore.renameVar(name, newname)
def parseRecipeFile(self, command, params):
"""
Parse the specified recipe file (with or without bbappends)
and return a datastore object representing the environment
for the recipe.
"""
fn = params[0]
appends = params[1]
appendlist = params[2]
if len(params) > 3:
config_data_dict = params[3]
config_data = command.remotedatastores.receive_datastore(config_data_dict)
else:
config_data = None
if appends:
if appendlist is not None:
appendfiles = appendlist
else:
appendfiles = command.cooker.collection.get_file_appends(fn)
else:
appendfiles = []
# We are calling bb.cache locally here rather than on the server,
# but that's OK because it doesn't actually need anything from
# the server barring the global datastore (which we have a remote
# version of)
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)['']
else:
# Use the standard path
parser = bb.cache.NoCache(command.cooker.databuilder)
envdata = parser.loadDataFull(fn, appendfiles)
idx = command.remotedatastores.store(envdata)
return DataStoreConnectionHandle(idx)
parseRecipeFile.readonly = True
class CommandsAsync:
"""
A class of asynchronous commands
@@ -587,15 +311,8 @@ class CommandsAsync:
"""
bfile = params[0]
task = params[1]
if len(params) > 2:
internal = params[2]
else:
internal = False
if internal:
command.cooker.buildFileInternal(bfile, task, fireevents=False, quietlog=True)
else:
command.cooker.buildFile(bfile, task)
command.cooker.buildFile(bfile, task)
buildFile.needcache = False
def buildTargets(self, command, params):
@@ -645,6 +362,17 @@ class CommandsAsync:
command.finishAsyncCommand()
generateTargetsTree.needcache = True
def findCoreBaseFiles(self, command, params):
"""
Find certain files in COREBASE directory. i.e. Layers
"""
subdir = params[0]
filename = params[1]
command.cooker.findCoreBaseFiles(subdir, filename)
command.finishAsyncCommand()
findCoreBaseFiles.needcache = False
def findConfigFiles(self, command, params):
"""
Find config files which provide appropriate values
@@ -744,22 +472,3 @@ class CommandsAsync:
command.finishAsyncCommand()
resetCooker.needcache = False
def clientComplete(self, command, params):
"""
Do the right thing when the controlling client exits
"""
command.cooker.clientComplete()
command.finishAsyncCommand()
clientComplete.needcache = False
def findSigInfo(self, command, params):
"""
Find signature info files via the signature generator
"""
pn = 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)
command.finishAsyncCommand()
findSigInfo.needcache = False

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,10 @@ class ConfigParameters(object):
self.options.pkgs_to_build = targets or []
self.options.tracking = False
if hasattr(self.options, "show_environment") and self.options.show_environment:
self.options.tracking = True
for key, val in self.options.__dict__.items():
setattr(self, key, val)
@@ -69,15 +73,15 @@ class ConfigParameters(object):
def updateToServer(self, server, environment):
options = {}
for o in ["abort", "force", "invalidate_stamp",
"verbose", "debug", "dry_run", "dump_signatures",
for o in ["abort", "tryaltconfigs", "force", "invalidate_stamp",
"verbose", "debug", "dry_run", "dump_signatures",
"debug_domains", "extra_assume_provided", "profile",
"prefile", "postfile", "server_timeout"]:
"prefile", "postfile"]:
options[o] = getattr(self.options, o)
ret, error = server.runCommand(["updateConfig", options, environment, sys.argv])
ret, error = server.runCommand(["updateConfig", options, environment])
if error:
raise Exception("Unable to update the server configuration with local parameters: %s" % error)
raise Exception("Unable to update the server configuration with local parameters: %s" % error)
def parseActions(self):
# Parse any commandline into actions
@@ -127,6 +131,8 @@ class CookerConfiguration(object):
self.extra_assume_provided = []
self.prefile = []
self.postfile = []
self.prefile_server = []
self.postfile_server = []
self.debug = 0
self.cmd = None
self.abort = True
@@ -138,13 +144,8 @@ class CookerConfiguration(object):
self.dump_signatures = []
self.dry_run = False
self.tracking = False
self.xmlrpcinterface = []
self.server_timeout = None
self.interface = []
self.writeeventlog = False
self.server_only = False
self.limited_deps = False
self.runall = []
self.runonly = []
self.env = {}
@@ -153,6 +154,7 @@ class CookerConfiguration(object):
if key in parameters.options.__dict__:
setattr(self, key, parameters.options.__dict__[key])
self.env = parameters.environment.copy()
self.tracking = parameters.tracking
def setServerRegIdleCallback(self, srcb):
self.server_register_idlecallback = srcb
@@ -168,7 +170,7 @@ class CookerConfiguration(object):
def __setstate__(self,state):
for k in state:
setattr(self, k, state[k])
setattr(self, k, state[k])
def catch_parse_error(func):
@@ -210,7 +212,7 @@ def _inherit(bbclass, data):
def findConfigFile(configfile, data):
search = []
bbpath = data.getVar("BBPATH")
bbpath = data.getVar("BBPATH", True)
if bbpath:
for i in bbpath.split(":"):
search.append(os.path.join(i, "conf", configfile))
@@ -225,27 +227,6 @@ def findConfigFile(configfile, data):
return None
#
# 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.
#
def findTopdir():
d = bb.data.init()
bbpath = None
if 'BBPATH' in os.environ:
bbpath = os.environ['BBPATH']
d.setVar('BBPATH', bbpath)
layerconf = findConfigFile("bblayers.conf", d)
if layerconf:
return os.path.dirname(os.path.dirname(layerconf))
if bbpath:
bitbakeconf = bb.utils.which(bbpath, "conf/bitbake.conf")
if bitbakeconf:
return os.path.dirname(os.path.dirname(bitbakeconf))
return None
class CookerDataBuilder(object):
def __init__(self, cookercfg, worker = False):
@@ -271,7 +252,7 @@ class CookerDataBuilder(object):
filtered_keys = bb.utils.approved_variables()
bb.data.inheritFromOS(self.basedata, self.savedenv, filtered_keys)
self.basedata.setVar("BB_ORIGENV", self.savedenv)
if worker:
self.basedata.setVar("BB_WORKERCONTEXT", "1")
@@ -305,13 +286,11 @@ class CookerDataBuilder(object):
self.data_hash = self.data.get_hash()
self.mcdata[''] = self.data
multiconfig = (self.data.getVar("BBMULTICONFIG") or "").split()
multiconfig = (self.data.getVar("BBMULTICONFIG", True) or "").split()
for config in multiconfig:
mcdata = self.parseConfigurationFiles(self.prefiles, self.postfiles, config)
bb.event.fire(bb.event.ConfigParsed(), mcdata)
self.mcdata[config] = mcdata
if multiconfig:
bb.event.fire(bb.event.MultiConfigParsed(self.mcdata), self.data)
except (SyntaxError, bb.BBHandledException):
raise bb.BBHandledException
@@ -322,18 +301,6 @@ class CookerDataBuilder(object):
logger.exception("Error parsing configuration files")
raise bb.BBHandledException
# Create a copy so we can reset at a later date when UIs disconnect
self.origdata = self.data
self.data = bb.data.createCopy(self.origdata)
self.mcdata[''] = self.data
def reset(self):
# We may not have run parseBaseConfiguration() yet
if not hasattr(self, 'origdata'):
return
self.data = bb.data.createCopy(self.origdata)
self.mcdata[''] = self.data
def _findLayerConf(self, data):
return findConfigFile("bblayers.conf", data)
@@ -353,7 +320,7 @@ class CookerDataBuilder(object):
data.setVar("TOPDIR", os.path.dirname(os.path.dirname(layerconf)))
data = parse_config_file(layerconf, data)
layers = (data.getVar('BBLAYERS') or "").split()
layers = (data.getVar('BBLAYERS', True) or "").split()
data = bb.data.createCopy(data)
approved = bb.utils.approved_variables()
@@ -376,30 +343,7 @@ class CookerDataBuilder(object):
data.delVar('LAYERDIR_RE')
data.delVar('LAYERDIR')
bbfiles_dynamic = (data.getVar('BBFILES_DYNAMIC') or "").split()
collections = (data.getVar('BBFILE_COLLECTIONS') or "").split()
invalid = []
for entry in bbfiles_dynamic:
parts = entry.split(":", 1)
if len(parts) != 2:
invalid.append(entry)
continue
l, f = parts
if l in collections:
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))
layerseries = set((data.getVar("LAYERSERIES_CORENAMES") or "").split())
for c in collections:
compat = set((data.getVar("LAYERSERIES_COMPAT_%s" % c) or "").split())
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)))
elif not compat and not data.getVar("BB_WORKERCONTEXT"):
bb.warn("Layer %s should set LAYERSERIES_COMPAT_%s in its conf/layer.conf file to list the core layer names it is compatible with." % (c, c))
if not data.getVar("BBPATH"):
if not data.getVar("BBPATH", True):
msg = "The BBPATH variable is not set"
if not layerconf:
msg += (" and bitbake did not find a conf/bblayers.conf file in"
@@ -414,7 +358,7 @@ class CookerDataBuilder(object):
data = parse_config_file(p, data)
# Handle any INHERITs and inherit the base class
bbclasses = ["base"] + (data.getVar('INHERIT') or "").split()
bbclasses = ["base"] + (data.getVar('INHERIT', True) or "").split()
for bbclass in bbclasses:
data = _inherit(bbclass, data)
@@ -426,7 +370,7 @@ class CookerDataBuilder(object):
parselog.critical("Undefined event handler function '%s'" % var)
sys.exit(1)
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", True) or "").split(), handlerfn, handlerln)
data.setVar('BBINCLUDED',bb.parse.get_file_depends(data))

View File

@@ -1,14 +1,48 @@
"""
Python Daemonizing helper
Originally based on code Copyright (C) 2005 Chad J. Schroeder but now heavily modified
to allow a function to be daemonized and return for bitbake use by Richard Purdie
Configurable daemon behaviors:
1.) The current working directory set to the "/" directory.
2.) The current file creation mode mask set to 0.
3.) Close all open files (1024).
4.) Redirect standard I/O streams to "/dev/null".
A failed call to fork() now raises an exception.
References:
1) Advanced Programming in the Unix Environment: W. Richard Stevens
http://www.apuebook.com/apue3e.html
2) The Linux Programming Interface: Michael Kerrisk
http://man7.org/tlpi/index.html
3) Unix Programming Frequently Asked Questions:
http://www.faqs.org/faqs/unix-faq/programmer/faq/
Modified to allow a function to be daemonized and return for
bitbake use by Richard Purdie
"""
import os
import sys
import io
import traceback
__author__ = "Chad J. Schroeder"
__copyright__ = "Copyright (C) 2005 Chad J. Schroeder"
__version__ = "0.2"
# Standard Python modules.
import os # Miscellaneous OS interfaces.
import sys # System-specific parameters and functions.
# Default daemon parameters.
# File mode creation mask of the daemon.
# For BitBake's children, we do want to inherit the parent umask.
UMASK = None
# Default maximum for the number of available file descriptors.
MAXFD = 1024
# The standard I/O file descriptors are redirected to /dev/null by default.
if (hasattr(os, "devnull")):
REDIRECT_TO = os.devnull
else:
REDIRECT_TO = "/dev/null"
def createDaemon(function, logfile):
"""
@@ -31,6 +65,36 @@ def createDaemon(function, logfile):
# leader of the new process group, we call os.setsid(). The process is
# also guaranteed not to have a controlling terminal.
os.setsid()
# Is ignoring SIGHUP necessary?
#
# It's often suggested that the SIGHUP signal should be ignored before
# the second fork to avoid premature termination of the process. The
# reason is that when the first child terminates, all processes, e.g.
# the second child, in the orphaned group will be sent a SIGHUP.
#
# "However, as part of the session management system, there are exactly
# two cases where SIGHUP is sent on the death of a process:
#
# 1) When the process that dies is the session leader of a session that
# is attached to a terminal device, SIGHUP is sent to all processes
# in the foreground process group of that terminal device.
# 2) When the death of a process causes a process group to become
# orphaned, and one or more processes in the orphaned group are
# stopped, then SIGHUP and SIGCONT are sent to all members of the
# orphaned group." [2]
#
# The first case can be ignored since the child is guaranteed not to have
# a controlling terminal. The second case isn't so easy to dismiss.
# The process group is orphaned when the first child terminates and
# POSIX.1 requires that every STOPPED process in an orphaned process
# group be sent a SIGHUP signal followed by a SIGCONT signal. Since the
# second child is not STOPPED though, we can safely forego ignoring the
# SIGHUP signal. In any case, there are no ill-effects if it is ignored.
#
# import signal # Set handlers for asynchronous events.
# signal.signal(signal.SIGHUP, signal.SIG_IGN)
try:
# Fork a second child and exit immediately to prevent zombies. This
# causes the second child process to be orphaned, making the init
@@ -44,39 +108,86 @@ def createDaemon(function, logfile):
except OSError as e:
raise Exception("%s [%d]" % (e.strerror, e.errno))
if (pid != 0):
if (pid == 0): # The second child.
# We probably don't want the file mode creation mask inherited from
# the parent, so we give the child complete control over permissions.
if UMASK is not None:
os.umask(UMASK)
else:
# Parent (the first child) of the second child.
# exit() or _exit()?
# _exit is like exit(), but it doesn't call any functions registered
# with atexit (and on_exit) or any registered signal handlers. It also
# closes any open file descriptors. Using exit() may cause all stdio
# streams to be flushed twice and any temporary files may be unexpectedly
# removed. It's therefore recommended that child branches of a fork()
# and the parent branch(es) of a daemon use _exit().
os._exit(0)
else:
os.waitpid(pid, 0)
# exit() or _exit()?
# _exit is like exit(), but it doesn't call any functions registered
# with atexit (and on_exit) or any registered signal handlers. It also
# closes any open file descriptors. Using exit() may cause all stdio
# streams to be flushed twice and any temporary files may be unexpectedly
# removed. It's therefore recommended that child branches of a fork()
# and the parent branch(es) of a daemon use _exit().
return
# The second child.
# Close all open file descriptors. This prevents the child from keeping
# open any file descriptors inherited from the parent. There is a variety
# of methods to accomplish this task. Three are listed below.
#
# Try the system configuration variable, SC_OPEN_MAX, to obtain the maximum
# number of open file descriptors to close. If it doesn't exist, use
# the default value (configurable).
#
# try:
# maxfd = os.sysconf("SC_OPEN_MAX")
# except (AttributeError, ValueError):
# maxfd = MAXFD
#
# OR
#
# if (os.sysconf_names.has_key("SC_OPEN_MAX")):
# maxfd = os.sysconf("SC_OPEN_MAX")
# else:
# maxfd = MAXFD
#
# OR
#
# Use the getrlimit method to retrieve the maximum file descriptor number
# that can be opened by this process. If there is no limit on the
# resource, use the default value.
#
import resource # Resource usage information.
maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
if (maxfd == resource.RLIM_INFINITY):
maxfd = MAXFD
# Iterate through and close all file descriptors.
# for fd in range(0, maxfd):
# try:
# os.close(fd)
# except OSError: # ERROR, fd wasn't open to begin with (ignored)
# pass
# Redirect the standard I/O file descriptors to the specified file. Since
# the daemon has no controlling terminal, most daemons redirect stdin,
# stdout, and stderr to /dev/null. This is done to prevent side-effects
# from reads and writes to the standard I/O file descriptors.
# This call to open is guaranteed to return the lowest file descriptor,
# which will be 0 (stdin), since it was closed above.
# os.open(REDIRECT_TO, os.O_RDWR) # standard input (0)
# Duplicate standard input to standard output and standard error.
# os.dup2(0, 1) # standard output (1)
# os.dup2(0, 2) # standard error (2)
# Replace standard fds with our own
si = open('/dev/null', 'r')
so = open(logfile, 'w')
se = so
# Replace those fds with our own
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
try:
so = open(logfile, 'a+')
se = so
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
except io.UnsupportedOperation:
sys.stdout = open(logfile, 'a+')
sys.stderr = sys.stdout
function()
try:
function()
except Exception as e:
traceback.print_exc()
finally:
bb.event.print_ui_queue()
os._exit(0)
os._exit(0)

View File

@@ -78,6 +78,59 @@ def initVar(var, d):
"""Non-destructive var init for data structure"""
d.initVar(var)
def setVar(var, value, d):
"""Set a variable to a given value"""
d.setVar(var, value)
def getVar(var, d, exp = False):
"""Gets the value of a variable"""
return d.getVar(var, exp)
def renameVar(key, newkey, d):
"""Renames a variable from key to newkey"""
d.renameVar(key, newkey)
def delVar(var, d):
"""Removes a variable from the data set"""
d.delVar(var)
def appendVar(var, value, d):
"""Append additional value to a variable"""
d.appendVar(var, value)
def setVarFlag(var, flag, flagvalue, d):
"""Set a flag for a given variable to a given value"""
d.setVarFlag(var, flag, flagvalue)
def getVarFlag(var, flag, d):
"""Gets given flag from given var"""
return d.getVarFlag(var, flag, False)
def delVarFlag(var, flag, d):
"""Removes a given flag from the variable's flags"""
d.delVarFlag(var, flag)
def setVarFlags(var, flags, d):
"""Set the flags for a given variable
Note:
setVarFlags will not clear previous
flags. Think of this method as
addVarFlags
"""
d.setVarFlags(var, flags)
def getVarFlags(var, d):
"""Gets a variable's flags"""
return d.getVarFlags(var)
def delVarFlags(var, d):
"""Removes a variable's flags"""
d.delVarFlags(var)
def keys(d):
"""Return a list of keys in d"""
return d.keys()
@@ -121,7 +174,7 @@ def inheritFromOS(d, savedenv, permitted):
for s in savedenv.keys():
if s in permitted:
try:
d.setVar(s, savedenv.getVar(s), op = 'from env')
d.setVar(s, savedenv.getVar(s, True), op = 'from env')
if s in exportlist:
d.setVarFlag(s, "export", True, op = 'auto env export')
except TypeError:
@@ -141,7 +194,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
try:
if all:
oval = d.getVar(var, False)
val = d.getVar(var)
val = d.getVar(var, True)
except (KeyboardInterrupt, bb.build.FuncFailed):
raise
except Exception as exc:
@@ -196,7 +249,7 @@ def emit_env(o=sys.__stdout__, d = init(), all=False):
keys = sorted((key for key in d.keys() if not key.startswith("__")), key=isfunc)
grouped = groupby(keys, isfunc)
for isfunc, keys in grouped:
for key in sorted(keys):
for key in keys:
emit_var(key, o, d, all and not isfunc) and o.write('\n')
def exported_keys(d):
@@ -208,9 +261,9 @@ def exported_vars(d):
k = list(exported_keys(d))
for key in k:
try:
value = d.getVar(key)
value = d.getVar(key, True)
except Exception as err:
bb.warn("%s: Unable to export ${%s}: %s" % (d.getVar("FILE"), key, err))
bb.warn("%s: Unable to export ${%s}: %s" % (d.getVar("FILE", True), key, err))
continue
if value is not None:
@@ -220,13 +273,13 @@ def emit_func(func, o=sys.__stdout__, d = init()):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func", False))
for key in sorted(keys):
for key in keys:
emit_var(key, o, d, False)
o.write('\n')
emit_var(func, o, d, False) and o.write('\n')
newdeps = bb.codeparser.ShellParser(func, logger).parse_shell(d.getVar(func))
newdeps |= set((d.getVarFlag(func, "vardeps") or "").split())
newdeps = bb.codeparser.ShellParser(func, logger).parse_shell(d.getVar(func, True))
newdeps |= set((d.getVarFlag(func, "vardeps", True) or "").split())
seen = set()
while newdeps:
deps = newdeps
@@ -235,8 +288,8 @@ def emit_func(func, o=sys.__stdout__, d = init()):
for dep in deps:
if d.getVarFlag(dep, "func", False) and not d.getVarFlag(dep, "python", False):
emit_var(dep, o, d, False) and o.write('\n')
newdeps |= bb.codeparser.ShellParser(dep, logger).parse_shell(d.getVar(dep))
newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split())
newdeps |= bb.codeparser.ShellParser(dep, logger).parse_shell(d.getVar(dep, True))
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
newdeps -= seen
_functionfmt = """
@@ -259,7 +312,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
pp = bb.codeparser.PythonParser(func, logger)
pp.parse_python(d.getVar(func, False))
newdeps = pp.execs
newdeps |= set((d.getVarFlag(func, "vardeps") or "").split())
newdeps |= set((d.getVarFlag(func, "vardeps", True) or "").split())
seen = set()
while newdeps:
deps = newdeps
@@ -271,7 +324,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
pp = bb.codeparser.PythonParser(dep, logger)
pp.parse_python(d.getVar(dep, False))
newdeps |= pp.execs
newdeps |= set((d.getVarFlag(dep, "vardeps") or "").split())
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
newdeps -= seen
def update_data(d):
@@ -290,19 +343,17 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
return deps, value
varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "exports", "postfuncs", "prefuncs", "lineno", "filename"]) or {}
vardeps = varflags.get("vardeps")
value = d.getVarFlag(key, "_content", False)
value = d.getVar(key, False)
def handle_contains(value, contains, d):
newvalue = ""
for k in sorted(contains):
l = (d.getVar(k) or "").split()
for item in sorted(contains[k]):
for word in item.split():
if not word in l:
newvalue += "\n%s{%s} = Unset" % (k, item)
break
l = (d.getVar(k, True) or "").split()
for word in sorted(contains[k]):
if word in l:
newvalue += "\n%s{%s} = Set" % (k, word)
else:
newvalue += "\n%s{%s} = Set" % (k, item)
newvalue += "\n%s{%s} = Unset" % (k, word)
if not newvalue:
return value
if not value:
@@ -315,7 +366,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
if varflags.get("python"):
parser = bb.codeparser.PythonParser(key, logger)
if value and "\t" in value:
logger.warning("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE")))
logger.warning("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno"))
deps = deps | parser.references
deps = deps | (keys & parser.execs)
@@ -359,8 +410,6 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
deps |= set((vardeps or "").split())
deps -= set(varflags.get("vardepsexclude", "").split())
except bb.parse.SkipRecipe:
raise
except Exception as e:
bb.warn("Exception during build_dependencies for %s" % key)
raise
@@ -372,7 +421,7 @@ def generate_dependencies(d):
keys = set(key for key in d if not key.startswith("__"))
shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False))
varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS')
varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS', True)
deps = {}
values = {}

View File

@@ -39,7 +39,7 @@ from bb.COW import COWDictBase
logger = logging.getLogger("BitBake.Data")
__setvar_keyword__ = ["_append", "_prepend", "_remove"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_remove)(_(?P<add>[^A-Z]*))?$')
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_remove)(_(?P<add>.*))?$')
__expand_var_regexp__ = re.compile(r"\${[^{}@\n\t :]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
@@ -108,7 +108,7 @@ class VariableParse:
varparse = self.d.expand_cache[key]
var = varparse.value
else:
var = self.d.getVarFlag(key, "_content")
var = self.d.getVarFlag(key, "_content", True)
self.references.add(key)
if var is not None:
return var
@@ -116,21 +116,13 @@ class VariableParse:
return match.group()
def python_sub(self, match):
if isinstance(match, str):
code = match
else:
code = match.group()[3:-1]
if "_remote_data" in self.d:
connector = self.d["_remote_data"]
return connector.expandPythonRef(self.varname, code, self.d)
code = match.group()[3:-1]
codeobj = compile(code.strip(), self.varname or "<expansion>", "eval")
parser = bb.codeparser.PythonParser(self.varname, logger)
parser.parse_python(code)
if self.varname:
vardeps = self.d.getVarFlag(self.varname, "vardeps")
vardeps = self.d.getVarFlag(self.varname, "vardeps", True)
if vardeps is None:
parser.log.flush()
else:
@@ -154,7 +146,7 @@ class DataContext(dict):
self['d'] = metadata
def __missing__(self, key):
value = self.metadata.getVar(key)
value = self.metadata.getVar(key, True)
if value is None or self.metadata.getVarFlag(key, 'func', False):
raise KeyError(key)
else:
@@ -230,19 +222,6 @@ class VariableHistory(object):
new.variables = self.variables.copy()
return new
def __getstate__(self):
vardict = {}
for k, v in self.variables.iteritems():
vardict[k] = v
return {'dataroot': self.dataroot,
'variables': vardict}
def __setstate__(self, state):
self.dataroot = state['dataroot']
self.variables = COWDictBase.copy()
for k, v in state['variables'].items():
self.variables[k] = v
def record(self, *kwonly, **loginfo):
if not self.dataroot._tracking:
return
@@ -268,15 +247,10 @@ class VariableHistory(object):
self.variables[var].append(loginfo.copy())
def variable(self, var):
remote_connector = self.dataroot.getVar('_remote_data', False)
if remote_connector:
varhistory = remote_connector.getVarHistory(var)
else:
varhistory = []
if var in self.variables:
varhistory.extend(self.variables[var])
return varhistory
return self.variables[var]
else:
return []
def emit(self, var, oval, val, o, d):
history = self.variable(var)
@@ -344,7 +318,7 @@ class VariableHistory(object):
the files in which they were added.
"""
history = self.variable(var)
finalitems = (d.getVar(var) or '').split()
finalitems = (d.getVar(var, True) or '').split()
filemap = {}
isset = False
for event in history:
@@ -452,11 +426,11 @@ class DataSmart(MutableMapping):
# Can end up here recursively so setup dummy values
self.overrides = []
self.overridesset = set()
self.overrides = (self.getVar("OVERRIDES") or "").split(":") or []
self.overrides = (self.getVar("OVERRIDES", True) or "").split(":") or []
self.overridesset = set(self.overrides)
self.inoverride = False
self.expand_cache = {}
newoverrides = (self.getVar("OVERRIDES") or "").split(":") or []
newoverrides = (self.getVar("OVERRIDES", True) or "").split(":") or []
if newoverrides == self.overrides:
break
self.overrides = newoverrides
@@ -473,22 +447,17 @@ class DataSmart(MutableMapping):
dest = self.dict
while dest:
if var in dest:
return dest[var], self.overridedata.get(var, None)
if "_remote_data" in dest:
connector = dest["_remote_data"]["_content"]
return connector.getVar(var)
return dest[var]
if "_data" not in dest:
break
dest = dest["_data"]
return None, self.overridedata.get(var, None)
def _makeShadowCopy(self, var):
if var in self.dict:
return
local_var, _ = self._findVar(var)
local_var = self._findVar(var)
if local_var:
self.dict[var] = copy.copy(local_var)
@@ -502,12 +471,6 @@ class DataSmart(MutableMapping):
if 'parsing' in loginfo:
parsing=True
if '_remote_data' in self.dict:
connector = self.dict["_remote_data"]["_content"]
res = connector.setVar(var, value)
if not res:
return
if 'op' not in loginfo:
loginfo['op'] = "set"
self.expand_cache = {}
@@ -546,8 +509,6 @@ class DataSmart(MutableMapping):
del self.dict[var]["_append"]
if "_prepend" in self.dict[var]:
del self.dict[var]["_prepend"]
if "_remove" in self.dict[var]:
del self.dict[var]["_remove"]
if var in self.overridedata:
active = []
self.need_overrides()
@@ -580,7 +541,7 @@ class DataSmart(MutableMapping):
nextnew = set()
self.overridevars.update(new)
for i in new:
vardata = self.expandWithRefs(self.getVar(i), i)
vardata = self.expandWithRefs(self.getVar(i, True), i)
nextnew.update(vardata.references)
nextnew.update(vardata.contains.keys())
new = nextnew
@@ -604,19 +565,13 @@ class DataSmart(MutableMapping):
if len(shortvar) == 0:
override = None
def getVar(self, var, expand=True, noweakdefault=False, parsing=False):
def getVar(self, var, expand, noweakdefault=False, parsing=False):
return self.getVarFlag(var, "_content", expand, noweakdefault, parsing)
def renameVar(self, key, newkey, **loginfo):
"""
Rename the variable key to newkey
"""
if '_remote_data' in self.dict:
connector = self.dict["_remote_data"]["_content"]
res = connector.renameVar(key, newkey)
if not res:
return
val = self.getVar(key, 0, parsing=True)
if val is not None:
loginfo['variable'] = newkey
@@ -660,12 +615,6 @@ class DataSmart(MutableMapping):
self.setVar(var + "_prepend", value, ignore=True, parsing=True)
def delVar(self, var, **loginfo):
if '_remote_data' in self.dict:
connector = self.dict["_remote_data"]["_content"]
res = connector.delVar(var)
if not res:
return
loginfo['detail'] = ""
loginfo['op'] = 'del'
self.varhistory.record(**loginfo)
@@ -692,12 +641,6 @@ class DataSmart(MutableMapping):
override = None
def setVarFlag(self, var, flag, value, **loginfo):
if '_remote_data' in self.dict:
connector = self.dict["_remote_data"]["_content"]
res = connector.setVarFlag(var, flag, value)
if not res:
return
self.expand_cache = {}
if 'op' not in loginfo:
loginfo['op'] = "set"
@@ -719,14 +662,14 @@ class DataSmart(MutableMapping):
self.dict["__exportlist"]["_content"] = set()
self.dict["__exportlist"]["_content"].add(var)
def getVarFlag(self, var, flag, expand=True, noweakdefault=False, parsing=False):
local_var, overridedata = self._findVar(var)
def getVarFlag(self, var, flag, expand, noweakdefault=False, parsing=False):
local_var = self._findVar(var)
value = None
if flag == "_content" and overridedata is not None and not parsing:
if flag == "_content" and var in self.overridedata and not parsing:
match = False
active = {}
self.need_overrides()
for (r, o) in overridedata:
for (r, o) in self.overridedata[var]:
# What about double overrides both with "_" in the name?
if o in self.overridesset:
active[o] = r
@@ -805,25 +748,18 @@ class DataSmart(MutableMapping):
if match:
removes.extend(self.expand(r).split())
if removes:
filtered = filter(lambda v: v not in removes,
value.split())
value = " ".join(filtered)
if expand and var in self.expand_cache:
# We need to ensure the expand cache has the correct value
# flag == "_content" here
self.expand_cache[var].value = value
filtered = filter(lambda v: v not in removes,
value.split())
value = " ".join(filtered)
if expand and var in self.expand_cache:
# We need to ensure the expand cache has the correct value
# flag == "_content" here
self.expand_cache[var].value = value
return value
def delVarFlag(self, var, flag, **loginfo):
if '_remote_data' in self.dict:
connector = self.dict["_remote_data"]["_content"]
res = connector.delVarFlag(var, flag)
if not res:
return
self.expand_cache = {}
local_var, _ = self._findVar(var)
local_var = self._findVar(var)
if not local_var:
return
if not var in self.dict:
@@ -866,7 +802,7 @@ class DataSmart(MutableMapping):
self.dict[var][i] = flags[i]
def getVarFlags(self, var, expand = False, internalflags=False):
local_var, _ = self._findVar(var)
local_var = self._findVar(var)
flags = {}
if local_var:
@@ -908,7 +844,7 @@ class DataSmart(MutableMapping):
data = DataSmart()
data.dict["_data"] = self.dict
data.varhistory = self.varhistory.copy()
data.varhistory.dataroot = data
data.varhistory.datasmart = data
data.inchistory = self.inchistory.copy()
data._tracking = self._tracking
@@ -939,7 +875,7 @@ class DataSmart(MutableMapping):
def localkeys(self):
for key in self.dict:
if key not in ['_data', '_remote_data']:
if key != '_data':
yield key
def __iter__(self):
@@ -948,7 +884,7 @@ class DataSmart(MutableMapping):
def keylist(d):
klist = set()
for key in d:
if key in ["_data", "_remote_data"]:
if key == "_data":
continue
if key in deleted:
continue
@@ -962,13 +898,6 @@ class DataSmart(MutableMapping):
if "_data" in d:
klist |= keylist(d["_data"])
if "_remote_data" in d:
connector = d["_remote_data"]["_content"]
for key in connector.getKeys():
if key in deleted:
continue
klist.add(key)
return klist
self.need_overrides()
@@ -1006,8 +935,9 @@ class DataSmart(MutableMapping):
data = {}
d = self.createCopy()
bb.data.expandKeys(d)
bb.data.update_data(d)
config_whitelist = set((d.getVar("BB_HASHCONFIG_WHITELIST") or "").split())
config_whitelist = set((d.getVar("BB_HASHCONFIG_WHITELIST", True) or "").split())
keys = set(key for key in iter(d) if not key.startswith("__"))
for key in keys:
if key in config_whitelist:
@@ -1026,6 +956,7 @@ class DataSmart(MutableMapping):
for key in ["__BBTASKS", "__BBANONFUNCS", "__BBHANDLERS"]:
bb_list = d.getVar(key, False) or []
bb_list.sort()
data.update({key:str(bb_list)})
if key == "__BBANONFUNCS":

View File

@@ -48,16 +48,6 @@ class Event(object):
def __init__(self):
self.pid = worker_pid
class HeartbeatEvent(Event):
"""Triggered at regular time intervals of 10 seconds. Other events can fire much more often
(runQueueTaskStarted when there are many short tasks) or not at all for long periods
of time (again runQueueTaskStarted, when there is just one long-running task), so this
event is more suitable for doing some task-independent work occassionally."""
def __init__(self, time):
Event.__init__(self)
self.time = time
Registered = 10
AlreadyRegistered = 14
@@ -149,34 +139,23 @@ def print_ui_queue():
# First check to see if we have any proper messages
msgprint = False
msgerrs = False
# Should we print to stderr?
for event in ui_queue[:]:
if isinstance(event, logging.LogRecord) and event.levelno >= logging.WARNING:
msgerrs = True
break
if msgerrs:
logger.addHandler(stderr)
else:
logger.addHandler(stdout)
for event in ui_queue[:]:
if isinstance(event, logging.LogRecord):
if event.levelno > logging.DEBUG:
if event.levelno >= logging.WARNING:
logger.addHandler(stderr)
else:
logger.addHandler(stdout)
logger.handle(event)
msgprint = True
if msgprint:
return
# Nope, so just print all of the messages we have (including debug messages)
if not msgprint:
for event in ui_queue[:]:
if isinstance(event, logging.LogRecord):
logger.handle(event)
if msgerrs:
logger.removeHandler(stderr)
else:
logger.removeHandler(stdout)
logger.addHandler(stdout)
for event in ui_queue[:]:
if isinstance(event, logging.LogRecord):
logger.handle(event)
def fire_ui_handlers(event, d):
global _thread_lock
@@ -223,12 +202,6 @@ def fire(event, d):
if worker_fire:
worker_fire(event, d)
else:
# If messages have been queued up, clear the queue
global _uiready, ui_queue
if _uiready and ui_queue:
for queue_event in ui_queue:
fire_ui_handlers(queue_event, d)
ui_queue = []
fire_ui_handlers(event, d)
def fire_from_worker(event, d):
@@ -281,11 +254,6 @@ def register(name, handler, mask=None, filename=None, lineno=None):
def remove(name, handler):
"""Remove an Event handler"""
_handlers.pop(name)
if name in _catchall_handlers:
_catchall_handlers.pop(name)
for event in _event_handler_map.keys():
if name in _event_handler_map[event]:
_event_handler_map[event].pop(name)
def get_handlers():
return _handlers
@@ -299,28 +267,20 @@ def set_eventfilter(func):
_eventfilter = func
def register_UIHhandler(handler, mainui=False):
if mainui:
global _uiready
_uiready = True
bb.event._ui_handler_seq = bb.event._ui_handler_seq + 1
_ui_handlers[_ui_handler_seq] = handler
level, debug_domains = bb.msg.constructLogOptions()
_ui_logfilters[_ui_handler_seq] = UIEventFilter(level, debug_domains)
if mainui:
global _uiready
_uiready = _ui_handler_seq
return _ui_handler_seq
def unregister_UIHhandler(handlerNum, mainui=False):
if mainui:
global _uiready
_uiready = False
def unregister_UIHhandler(handlerNum):
if handlerNum in _ui_handlers:
del _ui_handlers[handlerNum]
return
def get_uihandler():
if _uiready is False:
return None
return _uiready
# Class to allow filtering of events and specific filtering of LogRecords *before* we put them over the IPC
class UIEventFilter(object):
def __init__(self, level, debug_domains):
@@ -383,12 +343,6 @@ class OperationProgress(Event):
class ConfigParsed(Event):
"""Configuration Parsing Complete"""
class MultiConfigParsed(Event):
"""Multi-Config Parsing Complete"""
def __init__(self, mcdata):
self.mcdata = mcdata
Event.__init__(self)
class RecipeEvent(Event):
def __init__(self, fn):
self.fn = fn
@@ -397,17 +351,6 @@ class RecipeEvent(Event):
class RecipePreFinalise(RecipeEvent):
""" Recipe Parsing Complete but not yet finialised"""
class RecipeTaskPreProcess(RecipeEvent):
"""
Recipe Tasks about to be finalised
The list of tasks should be final at this point and handlers
are only able to change interdependencies
"""
def __init__(self, fn, tasklist):
self.fn = fn
self.tasklist = tasklist
Event.__init__(self)
class RecipeParsed(RecipeEvent):
""" Recipe Parsing Complete """
@@ -429,7 +372,7 @@ class StampUpdate(Event):
targets = property(getTargets)
class BuildBase(Event):
"""Base class for bitbake build events"""
"""Base class for bbmake run events"""
def __init__(self, n, p, failures = 0):
self._name = n
@@ -449,6 +392,12 @@ class BuildBase(Event):
def setName(self, name):
self._name = name
def getCfg(self):
return self.data
def setCfg(self, cfg):
self.data = cfg
def getFailures(self):
"""
Return the number of failed packages
@@ -457,6 +406,9 @@ class BuildBase(Event):
pkgs = property(getPkgs, setPkgs, None, "pkgs property")
name = property(getName, setName, None, "name property")
cfg = property(getCfg, setCfg, None, "cfg property")
class BuildInit(BuildBase):
"""buildFile or buildTargets was invoked"""
@@ -465,13 +417,13 @@ class BuildInit(BuildBase):
BuildBase.__init__(self, name, p)
class BuildStarted(BuildBase, OperationStarted):
"""Event when builds start"""
"""bbmake build run started"""
def __init__(self, n, p, failures = 0):
OperationStarted.__init__(self, "Building Started")
BuildBase.__init__(self, n, p, failures)
class BuildCompleted(BuildBase, OperationCompleted):
"""Event when builds have completed"""
"""bbmake build run completed"""
def __init__(self, total, n, p, failures=0, interrupted=0):
if not failures:
OperationCompleted.__init__(self, total, "Building Succeeded")
@@ -489,23 +441,6 @@ class DiskFull(Event):
self._free = freespace
self._mountpoint = mountpoint
class DiskUsageSample:
def __init__(self, available_bytes, free_bytes, total_bytes):
# Number of bytes available to non-root processes.
self.available_bytes = available_bytes
# Number of bytes available to root processes.
self.free_bytes = free_bytes
# Total capacity of the volume.
self.total_bytes = total_bytes
class MonitorDiskEvent(Event):
"""If BB_DISKMON_DIRS is set, then this event gets triggered each time disk space is checked.
Provides information about devices that are getting monitored."""
def __init__(self, disk_usage):
Event.__init__(self)
# hash of device root path -> DiskUsageSample
self.disk_usage = disk_usage
class NoProvider(Event):
"""No Provider for an Event"""
@@ -523,28 +458,6 @@ class NoProvider(Event):
def isRuntime(self):
return self._runtime
def __str__(self):
msg = ''
if self._runtime:
r = "R"
else:
r = ""
extra = ''
if not self._reasons:
if self._close_matches:
extra = ". Close matches:\n %s" % '\n '.join(self._close_matches)
if self._dependees:
msg = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s" % (r, self._item, ", ".join(self._dependees), r, extra)
else:
msg = "Nothing %sPROVIDES '%s'%s" % (r, self._item, extra)
if self._reasons:
for reason in self._reasons:
msg += '\n' + reason
return msg
class MultipleProviders(Event):
"""Multiple Providers"""
@@ -572,16 +485,6 @@ class MultipleProviders(Event):
"""
return self._candidates
def __str__(self):
msg = "Multiple providers are available for %s%s (%s)" % (self._is_runtime and "runtime " or "",
self._item,
", ".join(self._candidates))
rtime = ""
if self._is_runtime:
rtime = "R"
msg += "\nConsider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, self._item)
return msg
class ParseStarted(OperationStarted):
"""Recipe parsing for the runqueue has begun"""
def __init__(self, total):
@@ -675,6 +578,14 @@ class FilesMatchingFound(Event):
self._pattern = pattern
self._matches = matches
class CoreBaseFilesFound(Event):
"""
Event when a list of appropriate config files has been generated
"""
def __init__(self, paths):
Event.__init__(self)
self._paths = paths
class ConfigFilesFound(Event):
"""
Event when a list of appropriate config files has been generated
@@ -745,6 +656,19 @@ class LogHandler(logging.Handler):
record.taskpid = worker_pid
return True
class RequestPackageInfo(Event):
"""
Event to request package information
"""
class PackageInfo(Event):
"""
Package information for GUI
"""
def __init__(self, pkginfolist):
Event.__init__(self)
self._pkginfolist = pkginfolist
class MetadataEvent(Event):
"""
Generic event that target for OE-Core classes
@@ -822,10 +746,3 @@ class NetworkTestFailed(Event):
Event to indicate network test has failed
"""
class FindSigInfoResult(Event):
"""
Event to return results from findSigInfo command
"""
def __init__(self, result):
Event.__init__(self)
self.result = result

View File

@@ -35,11 +35,10 @@ import operator
import collections
import subprocess
import pickle
import errno
import bb.persist_data, bb.utils
import bb.checksum
from bb import data
import bb.process
import bb.event
__version__ = "2"
_checksum_cache = bb.checksum.FileChecksumCache()
@@ -49,11 +48,11 @@ logger = logging.getLogger("BitBake.Fetcher")
class BBFetchException(Exception):
"""Class all fetch exceptions inherit from"""
def __init__(self, message):
self.msg = message
Exception.__init__(self, message)
self.msg = message
Exception.__init__(self, message)
def __str__(self):
return self.msg
return self.msg
class UntrustedUrl(BBFetchException):
"""Exception raised when encountering a host not listed in BB_ALLOWED_NETWORKS"""
@@ -69,24 +68,24 @@ class UntrustedUrl(BBFetchException):
class MalformedUrl(BBFetchException):
"""Exception raised when encountering an invalid url"""
def __init__(self, url, message=''):
if message:
msg = message
else:
msg = "The URL: '%s' is invalid and cannot be interpreted" % url
self.url = url
BBFetchException.__init__(self, msg)
self.args = (url,)
if message:
msg = message
else:
msg = "The URL: '%s' is invalid and cannot be interpreted" % url
self.url = url
BBFetchException.__init__(self, msg)
self.args = (url,)
class FetchError(BBFetchException):
"""General fetcher exception when something happens incorrectly"""
def __init__(self, message, url = None):
if url:
if url:
msg = "Fetcher failure for URL: '%s'. %s" % (url, message)
else:
else:
msg = "Fetcher failure: %s" % message
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
class ChecksumError(FetchError):
"""Exception when mismatched checksum encountered"""
@@ -100,56 +99,49 @@ class NoChecksumError(FetchError):
class UnpackError(BBFetchException):
"""General fetcher exception when something happens incorrectly when unpacking"""
def __init__(self, message, url):
msg = "Unpack failure for URL: '%s'. %s" % (url, message)
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
msg = "Unpack failure for URL: '%s'. %s" % (url, message)
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
class NoMethodError(BBFetchException):
"""Exception raised when there is no method to obtain a supplied url or set of urls"""
def __init__(self, url):
msg = "Could not find a fetcher which supports the URL: '%s'" % url
self.url = url
BBFetchException.__init__(self, msg)
self.args = (url,)
msg = "Could not find a fetcher which supports the URL: '%s'" % url
self.url = url
BBFetchException.__init__(self, msg)
self.args = (url,)
class MissingParameterError(BBFetchException):
"""Exception raised when a fetch method is missing a critical parameter in the url"""
def __init__(self, missing, url):
msg = "URL: '%s' is missing the required parameter '%s'" % (url, missing)
self.url = url
self.missing = missing
BBFetchException.__init__(self, msg)
self.args = (missing, url)
msg = "URL: '%s' is missing the required parameter '%s'" % (url, missing)
self.url = url
self.missing = missing
BBFetchException.__init__(self, msg)
self.args = (missing, url)
class ParameterError(BBFetchException):
"""Exception raised when a url cannot be proccessed due to invalid parameters."""
def __init__(self, message, url):
msg = "URL: '%s' has invalid parameters. %s" % (url, message)
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
msg = "URL: '%s' has invalid parameters. %s" % (url, message)
self.url = url
BBFetchException.__init__(self, msg)
self.args = (message, url)
class NetworkAccess(BBFetchException):
"""Exception raised when network access is disabled but it is required."""
def __init__(self, url, cmd):
msg = "Network access disabled through BB_NO_NETWORK (or set indirectly due to use of BB_FETCH_PREMIRRORONLY) but access requested with command %s (for url %s)" % (cmd, url)
self.url = url
self.cmd = cmd
BBFetchException.__init__(self, msg)
self.args = (url, cmd)
msg = "Network access disabled through BB_NO_NETWORK (or set indirectly due to use of BB_FETCH_PREMIRRORONLY) but access requested with command %s (for url %s)" % (cmd, url)
self.url = url
self.cmd = cmd
BBFetchException.__init__(self, msg)
self.args = (url, cmd)
class NonLocalMethod(Exception):
def __init__(self):
Exception.__init__(self)
class MissingChecksumEvent(bb.event.Event):
def __init__(self, url, md5sum, sha256sum):
self.url = url
self.checksums = {'md5sum': md5sum,
'sha256sum': sha256sum}
bb.event.Event.__init__(self)
class URI(object):
"""
@@ -363,7 +355,7 @@ def decodeurl(url):
user, password, parameters).
"""
m = re.compile('(?P<type>[^:]*)://((?P<user>[^/;]+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
m = re.compile('(?P<type>[^:]*)://((?P<user>[^/]+)@)?(?P<location>[^;]+)(;(?P<parm>.*))?').match(url)
if not m:
raise MalformedUrl(url)
@@ -411,6 +403,8 @@ def encodeurl(decoded):
type, host, path, user, pswd, p = decoded
if not path:
raise MissingParameterError('path', "encoded from the data %s" % str(decoded))
if not type:
raise MissingParameterError('type', "encoded from the data %s" % str(decoded))
url = '%s://' % type
@@ -421,18 +415,17 @@ def encodeurl(decoded):
url += "@"
if host and type != "file":
url += "%s" % host
if path:
# Standardise path to ensure comparisons work
while '//' in path:
path = path.replace("//", "/")
url += "%s" % urllib.parse.quote(path)
# Standardise path to ensure comparisons work
while '//' in path:
path = path.replace("//", "/")
url += "%s" % urllib.parse.quote(path)
if p:
for parm in p:
url += ";%s=%s" % (parm, p[parm])
return url
def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
def uri_replace(ud, uri_find, uri_replace, replacements, d):
if not ud.url or not uri_find or not uri_replace:
logger.error("uri_replace: passed an undefined value, not replacing")
return None
@@ -462,7 +455,7 @@ def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
result_decoded[loc][k] = uri_replace_decoded[loc][k]
elif (re.match(regexp, uri_decoded[loc])):
if not uri_replace_decoded[loc]:
result_decoded[loc] = ""
result_decoded[loc] = ""
else:
for k in replacements:
uri_replace_decoded[loc] = uri_replace_decoded[loc].replace(k, replacements[k])
@@ -471,9 +464,9 @@ def uri_replace(ud, uri_find, uri_replace, replacements, d, mirrortarball=None):
if loc == 2:
# Handle path manipulations
basename = None
if uri_decoded[0] != uri_replace_decoded[0] and mirrortarball:
if uri_decoded[0] != uri_replace_decoded[0] and ud.mirrortarball:
# If the source and destination url types differ, must be a mirrortarball mapping
basename = os.path.basename(mirrortarball)
basename = os.path.basename(ud.mirrortarball)
# Kill parameters, they make no sense for mirror tarballs
uri_decoded[5] = {}
elif ud.localpath and ud.method.supports_checksum(ud):
@@ -498,7 +491,7 @@ def fetcher_init(d):
Calls before this must not hit the cache.
"""
# When to drop SCM head revisions controlled by user policy
srcrev_policy = d.getVar('BB_SRCREV_POLICY') or "clear"
srcrev_policy = d.getVar('BB_SRCREV_POLICY', True) or "clear"
if srcrev_policy == "cache":
logger.debug(1, "Keeping SRCREV cache due to cache policy of: %s", srcrev_policy)
elif srcrev_policy == "clear":
@@ -544,11 +537,7 @@ def fetcher_compare_revisions():
return False
def mirror_from_string(data):
mirrors = (data or "").replace('\\n',' ').split()
# Split into pairs
if len(mirrors) % 2 != 0:
bb.warn('Invalid mirror data %s, should have paired members.' % data)
return list(zip(*[iter(mirrors)]*2))
return [ i.split() for i in (data or "").replace('\\n','\n').split('\n') if i ]
def verify_checksum(ud, d, precomputed={}):
"""
@@ -583,7 +572,7 @@ def verify_checksum(ud, d, precomputed={}):
if ud.method.recommends_checksum(ud) and not ud.md5_expected and not ud.sha256_expected:
# If strict checking enabled and neither sum defined, raise error
strict = d.getVar("BB_STRICT_CHECKSUM") or "0"
strict = d.getVar("BB_STRICT_CHECKSUM", True) or "0"
if strict == "1":
logger.error('No checksum specified for %s, please add at least one to the recipe:\n'
'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
@@ -591,14 +580,6 @@ def verify_checksum(ud, d, precomputed={}):
ud.sha256_name, sha256data))
raise NoChecksumError('Missing SRC_URI checksum', ud.url)
bb.event.fire(MissingChecksumEvent(ud.url, md5data, sha256data), d)
if strict == "ignore":
return {
_MD5_KEY: md5data,
_SHA256_KEY: sha256data
}
# Log missing sums so user can more easily add them
logger.warning('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
'SRC_URI[%s] = "%s"',
@@ -640,28 +621,29 @@ def verify_donestamp(ud, d, origud=None):
Returns True, if the donestamp exists and is valid, False otherwise. When
returning False, any existing done stamps are removed.
"""
if not ud.needdonestamp or (origud and not origud.needdonestamp):
if not ud.needdonestamp:
return True
if not os.path.exists(ud.localpath):
# local path does not exist
if os.path.exists(ud.donestamp):
# done stamp exists, but the downloaded file does not; the done stamp
# must be incorrect, re-trigger the download
bb.utils.remove(ud.donestamp)
if not os.path.exists(ud.donestamp):
return False
if (not ud.method.supports_checksum(ud) or
(origud and not origud.method.supports_checksum(origud))):
# if done stamp exists and checksums not supported; assume the local
# file is current
return os.path.exists(ud.donestamp)
# done stamp exists, checksums not supported; assume the local file is
# current
return True
if not os.path.exists(ud.localpath):
# done stamp exists, but the downloaded file does not; the done stamp
# must be incorrect, re-trigger the download
bb.utils.remove(ud.donestamp)
return False
precomputed_checksums = {}
# Only re-use the precomputed checksums if the donestamp is newer than the
# file. Do not rely on the mtime of directories, though. If ud.localpath is
# a directory, there will probably not be any checksums anyway.
if os.path.exists(ud.donestamp) and (os.path.isdir(ud.localpath) or
if (os.path.isdir(ud.localpath) or
os.path.getmtime(ud.localpath) < os.path.getmtime(ud.donestamp)):
try:
with open(ud.donestamp, "rb") as cachefile:
@@ -736,18 +718,18 @@ def subprocess_setup():
def get_autorev(d):
# only not cache src rev in autorev case
if d.getVar('BB_SRCREV_POLICY') != "cache":
if d.getVar('BB_SRCREV_POLICY', True) != "cache":
d.setVar('BB_DONT_CACHE', '1')
return "AUTOINC"
def get_srcrev(d, method_name='sortable_revision'):
"""
Return the revision string, usually for use in the version string (PV) of the current package
Return the revsion string, usually for use in the version string (PV) of the current package
Most packages usually only have one SCM so we just pass on the call.
In the multi SCM case, we build a value based on SRCREV_FORMAT which must
have been set.
The idea here is that we put the string "AUTOINC+" into return value if the revisions are not
The idea here is that we put the string "AUTOINC+" into return value if the revisions are not
incremental, other code is then responsible for turning that into an increasing value (if needed)
A method_name can be supplied to retrieve an alternatively formatted revision from a fetcher, if
@@ -755,7 +737,7 @@ def get_srcrev(d, method_name='sortable_revision'):
"""
scms = []
fetcher = Fetch(d.getVar('SRC_URI').split(), d)
fetcher = Fetch(d.getVar('SRC_URI', True).split(), d)
urldata = fetcher.ud
for u in urldata:
if urldata[u].method.supports_srcrev():
@@ -775,7 +757,7 @@ def get_srcrev(d, method_name='sortable_revision'):
#
# Mutiple SCMs are in SRC_URI so we resort to SRCREV_FORMAT
#
format = d.getVar('SRCREV_FORMAT')
format = d.getVar('SRCREV_FORMAT', True)
if not format:
raise FetchError("The SRCREV_FORMAT variable must be set when multiple SCMs are used.")
@@ -799,7 +781,7 @@ def get_srcrev(d, method_name='sortable_revision'):
format = re.sub(name_to_rev_re, lambda match: name_to_rev[match.group(0)], format)
if seenautoinc:
format = "AUTOINC+" + format
format = "AUTOINC+" + format
return format
@@ -837,24 +819,12 @@ def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
if not cleanup:
cleanup = []
# If PATH contains WORKDIR which contains PV which contains SRCPV we
# can end up in circular recursion here so give the option of breaking it
# in a data store copy.
try:
d.getVar("PV")
except bb.data_smart.ExpansionError:
d = bb.data.createCopy(d)
d.setVar("PV", "fetcheravoidrecurse")
origenv = d.getVar("BB_ORIGENV", False)
for var in exportvars:
val = d.getVar(var) or (origenv and origenv.getVar(var))
val = d.getVar(var, True) or (origenv and origenv.getVar(var, True))
if val:
cmd = 'export ' + var + '=\"%s\"; %s' % (val, cmd)
# Disable pseudo as it may affect ssh, potentially causing it to hang.
cmd = 'export PSEUDO_DISABLED=1; ' + cmd
logger.debug(1, "Running %s", cmd)
success = False
@@ -886,15 +856,12 @@ def runfetchcmd(cmd, d, quiet=False, cleanup=None, log=None, workdir=None):
return output
def check_network_access(d, info, url):
def check_network_access(d, info = "", url = None):
"""
log remote network access, and error if BB_NO_NETWORK is set or the given
URI is untrusted
log remote network access, and error if BB_NO_NETWORK is set
"""
if d.getVar("BB_NO_NETWORK") == "1":
if d.getVar("BB_NO_NETWORK", True) == "1":
raise NetworkAccess(url, info)
elif not trusted_network(d, url):
raise UntrustedUrl(url, info)
else:
logger.debug(1, "Fetcher accessed the network with the command %s" % info)
@@ -909,47 +876,45 @@ def build_mirroruris(origud, mirrors, ld):
replacements["BASENAME"] = origud.path.split("/")[-1]
replacements["MIRRORNAME"] = origud.host.replace(':','.') + origud.path.replace('/', '.').replace('*', '.')
def adduri(ud, uris, uds, mirrors, tarballs):
def adduri(ud, uris, uds, mirrors):
for line in mirrors:
try:
(find, replace) = line
except ValueError:
continue
newuri = uri_replace(ud, find, replace, replacements, ld)
if not newuri or newuri in uris or newuri == origud.url:
continue
for tarball in tarballs:
newuri = uri_replace(ud, find, replace, replacements, ld, tarball)
if not newuri or newuri in uris or newuri == origud.url:
continue
if not trusted_network(ld, newuri):
logger.debug(1, "Mirror %s not in the list of trusted networks, skipping" % (newuri))
continue
if not trusted_network(ld, newuri):
logger.debug(1, "Mirror %s not in the list of trusted networks, skipping" % (newuri))
continue
# Create a local copy of the mirrors minus the current line
# this will prevent us from recursively processing the same line
# as well as indirect recursion A -> B -> C -> A
localmirrors = list(mirrors)
localmirrors.remove(line)
# Create a local copy of the mirrors minus the current line
# this will prevent us from recursively processing the same line
# as well as indirect recursion A -> B -> C -> A
localmirrors = list(mirrors)
localmirrors.remove(line)
try:
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))
try:
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))
try:
# setup_localpath of file:// urls may fail, we should still see
# if mirrors of the url exist
adduri(newud, uris, uds, localmirrors, tarballs)
except UnboundLocalError:
pass
continue
uris.append(newuri)
uds.append(newud)
# setup_localpath of file:// urls may fail, we should still see
# if mirrors of the url exist
adduri(newud, uris, uds, localmirrors)
except UnboundLocalError:
pass
continue
uris.append(newuri)
uds.append(newud)
adduri(newud, uris, uds, localmirrors, tarballs)
adduri(newud, uris, uds, localmirrors)
adduri(origud, uris, uds, mirrors, origud.mirrortarballs or [None])
adduri(origud, uris, uds, mirrors)
return uris, uds
@@ -993,26 +958,19 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
# We may be obtaining a mirror tarball which needs further processing by the real fetcher
# If that tarball is a local file:// we need to provide a symlink to it
dldir = ld.getVar("DL_DIR")
if origud.mirrortarballs and os.path.basename(ud.localpath) in origud.mirrortarballs and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
dldir = ld.getVar("DL_DIR", True)
if origud.mirrortarball and os.path.basename(ud.localpath) == os.path.basename(origud.mirrortarball) \
and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
# Create donestamp in old format to avoid triggering a re-download
if ud.donestamp:
bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
open(ud.donestamp, 'w').close()
dest = os.path.join(dldir, os.path.basename(ud.localpath))
if not os.path.exists(dest):
# In case this is executing without any file locks held (as is
# the case for file:// URLs), two tasks may end up here at the
# same time, in which case we do not want the second task to
# fail when the link has already been created by the first task.
try:
os.symlink(ud.localpath, dest)
except FileExistsError:
pass
os.symlink(ud.localpath, dest)
if not verify_donestamp(origud, ld) or origud.method.need_update(origud, ld):
origud.method.download(origud, ld)
if hasattr(origud.method, "build_mirror_data"):
if hasattr(origud.method,"build_mirror_data"):
origud.method.build_mirror_data(origud, ld)
return origud.localpath
# Otherwise the result is a local file:// and we symlink to it
@@ -1021,23 +979,13 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
# Broken symbolic link
os.unlink(origud.localpath)
# As per above, in case two tasks end up here simultaneously.
try:
os.symlink(ud.localpath, origud.localpath)
except FileExistsError:
pass
os.symlink(ud.localpath, origud.localpath)
update_stamp(origud, ld)
return ud.localpath
except bb.fetch2.NetworkAccess:
raise
except IOError as e:
if e.errno in [os.errno.ESTALE]:
logger.warning("Stale Error Observed %s." % ud.url)
return False
raise
except bb.fetch2.BBFetchException as e:
if isinstance(e, ChecksumError):
logger.warning("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
@@ -1084,14 +1032,14 @@ def trusted_network(d, url):
BB_ALLOWED_NETWORKS is set globally or for a specific recipe.
Note: modifies SRC_URI & mirrors.
"""
if d.getVar('BB_NO_NETWORK') == "1":
if d.getVar('BB_NO_NETWORK', True) == "1":
return True
pkgname = d.expand(d.getVar('PN', False))
trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname, False)
if not trusted_hosts:
trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS')
trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS', True)
# Not enabled.
if not trusted_hosts:
@@ -1123,7 +1071,7 @@ def srcrev_internal_helper(ud, d, name):
"""
srcrev = None
pn = d.getVar("PN")
pn = d.getVar("PN", True)
attempts = []
if name != '' and pn:
attempts.append("SRCREV_%s_pn-%s" % (name, pn))
@@ -1134,7 +1082,7 @@ def srcrev_internal_helper(ud, d, name):
attempts.append("SRCREV")
for a in attempts:
srcrev = d.getVar(a)
srcrev = d.getVar(a, True)
if srcrev and srcrev != "INVALID":
break
@@ -1149,7 +1097,7 @@ def srcrev_internal_helper(ud, d, name):
if srcrev == "INVALID" or not srcrev:
return parmrev
if srcrev != parmrev:
raise FetchError("Conflicting revisions (%s from SRCREV and %s from the url) found, please specify one valid value" % (srcrev, parmrev))
raise FetchError("Conflicting revisions (%s from SRCREV and %s from the url) found, please spcify one valid value" % (srcrev, parmrev))
return parmrev
if srcrev == "INVALID" or not srcrev:
@@ -1167,7 +1115,7 @@ def get_checksum_file_list(d):
"""
fetch = Fetch([], d, cache = False, localonly = True)
dl_dir = d.getVar('DL_DIR')
dl_dir = d.getVar('DL_DIR', True)
filelist = []
for u in fetch.urls:
ud = fetch.ud[u]
@@ -1181,9 +1129,9 @@ def get_checksum_file_list(d):
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):
bb.warn("Getting checksum for %s SRC_URI entry %s: file not found except in DL_DIR" % (d.getVar('PN'), os.path.basename(f)))
bb.warn("Getting checksum for %s SRC_URI entry %s: file not found except in DL_DIR" % (d.getVar('PN', True), os.path.basename(f)))
else:
bb.warn("Unable to get checksum for %s SRC_URI entry %s: file could not be found" % (d.getVar('PN'), os.path.basename(f)))
bb.warn("Unable to get checksum for %s SRC_URI entry %s: file could not be found" % (d.getVar('PN', True), os.path.basename(f)))
filelist.append(f + ":" + str(os.path.exists(f)))
return " ".join(filelist)
@@ -1209,10 +1157,10 @@ class FetchData(object):
self.localfile = ""
self.localpath = None
self.lockfile = None
self.mirrortarballs = []
self.mirrortarball = None
self.basename = None
self.basepath = None
(self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(d.expand(url))
(self.type, self.host, self.path, self.user, self.pswd, self.parm) = decodeurl(data.expand(url, d))
self.date = self.getSRCDate(d)
self.url = url
if not self.user and "user" in self.parm:
@@ -1229,16 +1177,16 @@ class FetchData(object):
self.sha256_name = "sha256sum"
if self.md5_name in self.parm:
self.md5_expected = self.parm[self.md5_name]
elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3"]:
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.md5_expected = None
else:
self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name)
self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name, True)
if self.sha256_name in self.parm:
self.sha256_expected = self.parm[self.sha256_name]
elif self.type not in ["http", "https", "ftp", "ftps", "sftp", "s3"]:
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.sha256_expected = None
else:
self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name)
self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name, True)
self.ignore_checksums = False
self.names = self.parm.get("name",'default').split(',')
@@ -1247,7 +1195,7 @@ class FetchData(object):
for m in methods:
if m.supports(self, d):
self.method = m
break
break
if not self.method:
raise NoMethodError(url)
@@ -1256,7 +1204,7 @@ class FetchData(object):
raise NonLocalMethod()
if self.parm.get("proto", None) and "protocol" not in self.parm:
logger.warning('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN'))
logger.warning('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN', True))
self.parm["protocol"] = self.parm.get("proto", None)
if hasattr(self.method, "urldata_init"):
@@ -1269,7 +1217,7 @@ class FetchData(object):
elif self.localfile:
self.localpath = self.method.localpath(self, d)
dldir = d.getVar("DL_DIR")
dldir = d.getVar("DL_DIR", True)
if not self.needdonestamp:
return
@@ -1282,12 +1230,12 @@ class FetchData(object):
elif self.basepath or self.basename:
basepath = dldir + os.sep + (self.basepath or self.basename)
else:
bb.fatal("Can't determine lock path for url %s" % url)
bb.fatal("Can't determine lock path for url %s" % url)
self.donestamp = basepath + '.done'
self.lockfile = basepath + '.lock'
def setup_revisions(self, d):
def setup_revisons(self, d):
self.revisions = {}
for name in self.names:
self.revisions[name] = srcrev_internal_helper(self, d, name)
@@ -1309,12 +1257,12 @@ class FetchData(object):
if "srcdate" in self.parm:
return self.parm['srcdate']
pn = d.getVar("PN")
pn = d.getVar("PN", True)
if pn:
return d.getVar("SRCDATE_%s" % pn) or d.getVar("SRCDATE") or d.getVar("DATE")
return d.getVar("SRCDATE_%s" % pn, True) or d.getVar("SRCDATE", True) or d.getVar("DATE", True)
return d.getVar("SRCDATE") or d.getVar("DATE")
return d.getVar("SRCDATE", True) or d.getVar("DATE", True)
class FetchMethod(object):
"""Base class for 'fetch'ing data"""
@@ -1334,7 +1282,7 @@ class FetchMethod(object):
Can also setup variables in urldata for use in go (saving code duplication
and duplicate code execution)
"""
return os.path.join(d.getVar("DL_DIR"), urldata.localfile)
return os.path.join(data.getVar("DL_DIR", d, True), urldata.localfile)
def supports_checksum(self, urldata):
"""
@@ -1345,13 +1293,13 @@ class FetchMethod(object):
if os.path.isdir(urldata.localpath) == True:
return False
if urldata.localpath.find("*") != -1:
return False
return False
return True
def recommends_checksum(self, urldata):
"""
Is the backend on where checksumming is recommended (should warnings
Is the backend on where checksumming is recommended (should warnings
be displayed if there is no checksum)?
"""
return False
@@ -1426,7 +1374,7 @@ class FetchMethod(object):
cmd = 'gzip -dc %s > %s' % (file, efile)
elif file.endswith('.bz2'):
cmd = 'bzip2 -dc %s > %s' % (file, efile)
elif file.endswith('.txz') or file.endswith('.tar.xz'):
elif file.endswith('.tar.xz'):
cmd = 'xz -dc %s | tar x --no-same-owner -f -' % file
elif file.endswith('.xz'):
cmd = 'xz -dc %s > %s' % (file, efile)
@@ -1434,10 +1382,6 @@ class FetchMethod(object):
cmd = 'lzip -dc %s | tar x --no-same-owner -f -' % file
elif file.endswith('.lz'):
cmd = 'lzip -dc %s > %s' % (file, efile)
elif file.endswith('.tar.7z'):
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('.zip') or file.endswith('.jar'):
try:
dos = bb.utils.to_boolean(urldata.parm.get('dos'), False)
@@ -1469,6 +1413,10 @@ class FetchMethod(object):
else:
raise UnpackError("Unable to unpack deb/ipk package - could not list contents", urldata.url)
cmd = 'ar x %s %s && tar --no-same-owner -xpf %s && rm %s' % (file, datafile, datafile, datafile)
elif file.endswith('.tar.7z'):
cmd = '7z x -so %s | tar xf - ' % file
elif file.endswith('.7z'):
cmd = '7za x -y %s 1>/dev/null' % file
# If 'subdir' param exists, create a dir and use it as destination for unpack cmd
if 'subdir' in urldata.parm:
@@ -1502,7 +1450,7 @@ class FetchMethod(object):
if not cmd:
return
path = data.getVar('PATH')
path = data.getVar('PATH', True)
if path:
cmd = "PATH=\"%s\" %s" % (path, cmd)
bb.note("Unpacking %s to %s/" % (file, unpackdir))
@@ -1559,15 +1507,7 @@ class FetchMethod(object):
def generate_revision_key(self, ud, d, name):
key = self._revision_key(ud, d, name)
return "%s-%s" % (key, d.getVar("PN") or "")
def latest_versionstring(self, ud, d):
"""
Compute the latest release name like "x.y.x" in "x.y.x+gitHASH"
by searching through the tags output of ls-remote, comparing
versions and returning the highest match as a (version, revision) pair.
"""
return ('', '')
return "%s-%s" % (key, d.getVar("PN", True) or "")
class Fetch(object):
def __init__(self, urls, d, cache = True, localonly = False, connection_cache = None):
@@ -1575,14 +1515,14 @@ class Fetch(object):
raise Exception("bb.fetch2.Fetch.__init__: cannot set cache and localonly at same time")
if len(urls) == 0:
urls = d.getVar("SRC_URI").split()
urls = d.getVar("SRC_URI", True).split()
self.urls = urls
self.d = d
self.ud = {}
self.connection_cache = connection_cache
fn = d.getVar('FILE')
mc = d.getVar('__BBMULTICONFIG') or ""
fn = d.getVar('FILE', True)
mc = d.getVar('__BBMULTICONFIG', True) or ""
if cache and fn and mc + fn in urldata_cache:
self.ud = urldata_cache[mc + fn]
@@ -1625,8 +1565,8 @@ class Fetch(object):
if not urls:
urls = self.urls
network = self.d.getVar("BB_NO_NETWORK")
premirroronly = (self.d.getVar("BB_FETCH_PREMIRRORONLY") == "1")
network = self.d.getVar("BB_NO_NETWORK", True)
premirroronly = (self.d.getVar("BB_FETCH_PREMIRRORONLY", True) == "1")
for u in urls:
ud = self.ud[u]
@@ -1639,22 +1579,13 @@ class Fetch(object):
try:
self.d.setVar("BB_NO_NETWORK", network)
if verify_donestamp(ud, self.d) and not m.need_update(ud, self.d):
localpath = ud.localpath
elif m.try_premirror(ud, self.d):
logger.debug(1, "Trying PREMIRRORS")
mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
mirrors = mirror_from_string(self.d.getVar('PREMIRRORS', True))
localpath = try_mirrors(self, self.d, ud, mirrors, False)
if localpath:
try:
# early checksum verification so that if the checksum of the premirror
# contents mismatch the fetcher can still try upstream and mirrors
update_stamp(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))
localpath = ""
if premirroronly:
self.d.setVar("BB_NO_NETWORK", "1")
@@ -1693,7 +1624,7 @@ class Fetch(object):
if not verified_stamp:
m.clean(ud, self.d)
logger.debug(1, "Trying MIRRORS")
mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
mirrors = mirror_from_string(self.d.getVar('MIRRORS', True))
localpath = try_mirrors(self, self.d, ud, mirrors)
if not localpath or ((not os.path.exists(localpath)) and localpath.find("*") == -1):
@@ -1703,11 +1634,6 @@ class Fetch(object):
update_stamp(ud, self.d)
except IOError as e:
if e.errno in [os.errno.ESTALE]:
logger.error("Stale Error Observed %s." % u)
raise ChecksumError("Stale Error Detected")
except BBFetchException as e:
if isinstance(e, ChecksumError):
logger.error("Checksum failure fetching %s" % u)
@@ -1731,14 +1657,15 @@ class Fetch(object):
m = ud.method
logger.debug(1, "Testing URL %s", u)
# First try checking uri, u, from PREMIRRORS
mirrors = mirror_from_string(self.d.getVar('PREMIRRORS'))
mirrors = mirror_from_string(self.d.getVar('PREMIRRORS', True))
ret = try_mirrors(self, self.d, ud, mirrors, True)
if not ret:
# Next try checking from the original uri, u
ret = m.checkstatus(self, ud, self.d)
if not ret:
try:
ret = m.checkstatus(self, ud, self.d)
except:
# Finally, try checking uri, u, from MIRRORS
mirrors = mirror_from_string(self.d.getVar('MIRRORS'))
mirrors = mirror_from_string(self.d.getVar('MIRRORS', True))
ret = try_mirrors(self, self.d, ud, mirrors, True)
if not ret:
@@ -1746,7 +1673,7 @@ class Fetch(object):
def unpack(self, root, urls=None):
"""
Unpack urls to root
Check all urls exist upstream
"""
if not urls:
@@ -1836,7 +1763,6 @@ from . import svn
from . import wget
from . import ssh
from . import sftp
from . import s3
from . import perforce
from . import bzr
from . import hg
@@ -1854,7 +1780,6 @@ methods.append(gitannex.GitANNEX())
methods.append(cvs.Cvs())
methods.append(ssh.SSH())
methods.append(sftp.SFTP())
methods.append(s3.S3())
methods.append(perforce.Perforce())
methods.append(bzr.Bzr())
methods.append(hg.Hg())

View File

@@ -27,6 +27,7 @@ import os
import sys
import logging
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import runfetchcmd
@@ -42,14 +43,14 @@ class Bzr(FetchMethod):
"""
# Create paths to bzr checkouts
relpath = self._strip_leading_slashes(ud.path)
ud.pkgdir = os.path.join(d.expand('${BZRDIR}'), ud.host, relpath)
ud.pkgdir = os.path.join(data.expand('${BZRDIR}', d), ud.host, relpath)
ud.setup_revisions(d)
ud.setup_revisons(d)
if not ud.revision:
ud.revision = self.latest_revision(ud, d)
ud.localfile = d.expand('bzr_%s_%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.revision))
ud.localfile = data.expand('bzr_%s_%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.revision), d)
def _buildbzrcommand(self, ud, d, command):
"""
@@ -57,7 +58,7 @@ class Bzr(FetchMethod):
command is "fetch", "update", "revno"
"""
basecmd = d.expand('${FETCHCMD_bzr}')
basecmd = data.expand('${FETCHCMD_bzr}', d)
proto = ud.parm.get('protocol', 'http')

View File

@@ -65,10 +65,12 @@ import os
import sys
import shutil
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
from distutils import spawn
class ClearCase(FetchMethod):
"""Class to fetch urls via 'clearcase'"""
@@ -106,13 +108,13 @@ class ClearCase(FetchMethod):
else:
ud.module = ""
ud.basecmd = d.getVar("FETCHCMD_ccrc") or "/usr/bin/env cleartool || rcleartool"
ud.basecmd = d.getVar("FETCHCMD_ccrc", True) or spawn.find_executable("cleartool") or spawn.find_executable("rcleartool")
if d.getVar("SRCREV") == "INVALID":
if data.getVar("SRCREV", d, True) == "INVALID":
raise FetchError("Set a valid SRCREV for the clearcase fetcher in your recipe, e.g. SRCREV = \"/main/LATEST\" or any other label of your choice.")
ud.label = d.getVar("SRCREV", False)
ud.customspec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC")
ud.customspec = d.getVar("CCASE_CUSTOM_CONFIG_SPEC", True)
ud.server = "%s://%s%s" % (ud.proto, ud.host, ud.path)
@@ -122,7 +124,7 @@ class ClearCase(FetchMethod):
ud.viewname = "%s-view%s" % (ud.identifier, d.getVar("DATETIME", d, True))
ud.csname = "%s-config-spec" % (ud.identifier)
ud.ccasedir = os.path.join(d.getVar("DL_DIR"), ud.type)
ud.ccasedir = os.path.join(data.getVar("DL_DIR", d, True), ud.type)
ud.viewdir = os.path.join(ud.ccasedir, ud.viewname)
ud.configspecfile = os.path.join(ud.ccasedir, ud.csname)
ud.localfile = "%s.tar.gz" % (ud.identifier)
@@ -142,7 +144,7 @@ class ClearCase(FetchMethod):
self.debug("configspecfile = %s" % ud.configspecfile)
self.debug("localfile = %s" % ud.localfile)
ud.localfile = os.path.join(d.getVar("DL_DIR"), ud.localfile)
ud.localfile = os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
def _build_ccase_command(self, ud, command):
"""

View File

@@ -63,7 +63,7 @@ class Cvs(FetchMethod):
if 'fullpath' in ud.parm:
fullpath = '_fullpath'
ud.localfile = d.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath))
ud.localfile = bb.data.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath), d)
def need_update(self, ud, d):
if (ud.date == "now"):
@@ -87,10 +87,10 @@ class Cvs(FetchMethod):
cvsroot = ud.path
else:
cvsroot = ":" + method
cvsproxyhost = d.getVar('CVS_PROXY_HOST')
cvsproxyhost = d.getVar('CVS_PROXY_HOST', True)
if cvsproxyhost:
cvsroot += ";proxy=" + cvsproxyhost
cvsproxyport = d.getVar('CVS_PROXY_PORT')
cvsproxyport = d.getVar('CVS_PROXY_PORT', True)
if cvsproxyport:
cvsroot += ";proxyport=" + cvsproxyport
cvsroot += ":" + ud.user
@@ -110,7 +110,7 @@ class Cvs(FetchMethod):
if ud.tag:
options.append("-r %s" % ud.tag)
cvsbasecmd = d.getVar("FETCHCMD_cvs")
cvsbasecmd = d.getVar("FETCHCMD_cvs", True)
cvscmd = cvsbasecmd + " '-d" + cvsroot + "' co " + " ".join(options) + " " + ud.module
cvsupdatecmd = cvsbasecmd + " '-d" + cvsroot + "' update -d -P " + " ".join(options)
@@ -120,8 +120,8 @@ class Cvs(FetchMethod):
# create module directory
logger.debug(2, "Fetch: checking for module directory")
pkg = d.getVar('PN')
pkgdir = os.path.join(d.getVar('CVSDIR'), pkg)
pkg = d.getVar('PN', True)
pkgdir = os.path.join(d.getVar('CVSDIR', True), pkg)
moddir = os.path.join(pkgdir, localdir)
workdir = None
if os.access(os.path.join(moddir, 'CVS'), os.R_OK):
@@ -164,8 +164,8 @@ 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)
pkg = d.getVar('PN', True)
pkgdir = os.path.join(d.getVar("CVSDIR", True), pkg)
bb.utils.remove(pkgdir, True)
bb.utils.remove(ud.localpath)

View File

@@ -50,7 +50,7 @@ Supported SRC_URI options are:
The default is "0", set nobranch=1 if needed.
- usehead
For local git:// urls to use the current branch HEAD as the revision for use with
For local git:// urls to use the current branch HEAD as the revsion for use with
AUTOREV. Implies nobranch.
"""
@@ -70,15 +70,13 @@ Supported SRC_URI options are:
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import collections
import errno
import fnmatch
import os
import re
import subprocess
import tempfile
import bb
import errno
import bb.progress
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
@@ -125,9 +123,6 @@ class GitProgressHandler(bb.progress.LineFilterProgressHandler):
class Git(FetchMethod):
bitbake_dir = os.path.abspath(os.path.join(os.path.dirname(os.path.join(os.path.abspath(__file__))), '..', '..', '..'))
make_shallow_path = os.path.join(bitbake_dir, 'bin', 'git-make-shallow')
"""Class to fetch a module or modules from git repositories"""
def init(self, d):
pass
@@ -178,68 +173,20 @@ class Git(FetchMethod):
branches = ud.parm.get("branch", "master").split(',')
if len(branches) != len(ud.names):
raise bb.fetch2.ParameterError("The number of name and branch parameters is not balanced", ud.url)
ud.cloneflags = "-s -n"
if ud.bareclone:
ud.cloneflags += " --mirror"
ud.shallow = d.getVar("BB_GIT_SHALLOW") == "1"
ud.shallow_extra_refs = (d.getVar("BB_GIT_SHALLOW_EXTRA_REFS") or "").split()
depth_default = d.getVar("BB_GIT_SHALLOW_DEPTH")
if depth_default is not None:
try:
depth_default = int(depth_default or 0)
except ValueError:
raise bb.fetch2.FetchError("Invalid depth for BB_GIT_SHALLOW_DEPTH: %s" % depth_default)
else:
if depth_default < 0:
raise bb.fetch2.FetchError("Invalid depth for BB_GIT_SHALLOW_DEPTH: %s" % depth_default)
else:
depth_default = 1
ud.shallow_depths = collections.defaultdict(lambda: depth_default)
revs_default = d.getVar("BB_GIT_SHALLOW_REVS", True)
ud.shallow_revs = []
ud.branches = {}
for pos, name in enumerate(ud.names):
branch = branches[pos]
for name in ud.names:
branch = branches[ud.names.index(name)]
ud.branches[name] = branch
ud.unresolvedrev[name] = branch
shallow_depth = d.getVar("BB_GIT_SHALLOW_DEPTH_%s" % name)
if shallow_depth is not None:
try:
shallow_depth = int(shallow_depth or 0)
except ValueError:
raise bb.fetch2.FetchError("Invalid depth for BB_GIT_SHALLOW_DEPTH_%s: %s" % (name, shallow_depth))
else:
if shallow_depth < 0:
raise bb.fetch2.FetchError("Invalid depth for BB_GIT_SHALLOW_DEPTH_%s: %s" % (name, shallow_depth))
ud.shallow_depths[name] = shallow_depth
revs = d.getVar("BB_GIT_SHALLOW_REVS_%s" % name)
if revs is not None:
ud.shallow_revs.extend(revs.split())
elif revs_default is not None:
ud.shallow_revs.extend(revs_default.split())
if (ud.shallow and
not ud.shallow_revs and
all(ud.shallow_depths[n] == 0 for n in ud.names)):
# Shallow disabled for this URL
ud.shallow = False
if ud.usehead:
ud.unresolvedrev['default'] = 'HEAD'
ud.basecmd = d.getVar("FETCHCMD_git") or "git -c core.fsyncobjectfiles=0"
ud.basecmd = data.getVar("FETCHCMD_git", d, True) or "git -c core.fsyncobjectfiles=0"
write_tarballs = d.getVar("BB_GENERATE_MIRROR_TARBALLS") or "0"
ud.write_tarballs = write_tarballs != "0" or ud.rebaseable
ud.write_shallow_tarballs = (d.getVar("BB_GENERATE_SHALLOW_TARBALLS") or write_tarballs) != "0"
ud.write_tarballs = ((data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) or "0") != "0") or ud.rebaseable
ud.setup_revisions(d)
ud.setup_revisons(d)
for name in ud.names:
# Ensure anything that doesn't look like a sha256 checksum/revision is translated into one
@@ -259,42 +206,13 @@ class Git(FetchMethod):
if ud.rebaseable:
for name in ud.names:
gitsrcname = gitsrcname + '_' + ud.revisions[name]
dl_dir = d.getVar("DL_DIR")
gitdir = d.getVar("GITDIR") or (dl_dir + "/git2/")
ud.mirrortarball = 'git2_%s.tar.gz' % (gitsrcname)
ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
gitdir = d.getVar("GITDIR", True) or (d.getVar("DL_DIR", True) + "/git2/")
ud.clonedir = os.path.join(gitdir, gitsrcname)
ud.localfile = ud.clonedir
mirrortarball = 'git2_%s.tar.gz' % gitsrcname
ud.fullmirror = os.path.join(dl_dir, mirrortarball)
ud.mirrortarballs = [mirrortarball]
if ud.shallow:
tarballname = gitsrcname
if ud.bareclone:
tarballname = "%s_bare" % tarballname
if ud.shallow_revs:
tarballname = "%s_%s" % (tarballname, "_".join(sorted(ud.shallow_revs)))
for name, revision in sorted(ud.revisions.items()):
tarballname = "%s_%s" % (tarballname, ud.revisions[name][:7])
depth = ud.shallow_depths[name]
if depth:
tarballname = "%s-%s" % (tarballname, depth)
shallow_refs = []
if not ud.nobranch:
shallow_refs.extend(ud.branches.values())
if ud.shallow_extra_refs:
shallow_refs.extend(r.replace('refs/heads/', '').replace('*', 'ALL') for r in ud.shallow_extra_refs)
if shallow_refs:
tarballname = "%s_%s" % (tarballname, "_".join(sorted(shallow_refs)).replace('/', '.'))
fetcher = self.__class__.__name__.lower()
ud.shallowtarball = '%sshallow_%s.tar.gz' % (fetcher, tarballname)
ud.fullshallow = os.path.join(dl_dir, ud.shallowtarball)
ud.mirrortarballs.insert(0, ud.shallowtarball)
def localpath(self, ud, d):
return ud.clonedir
@@ -304,8 +222,6 @@ class Git(FetchMethod):
for name in ud.names:
if not self._contains_ref(ud, d, name, ud.clonedir):
return True
if ud.shallow and ud.write_shallow_tarballs and not os.path.exists(ud.fullshallow):
return True
if ud.write_tarballs and not os.path.exists(ud.fullmirror):
return True
return False
@@ -313,7 +229,7 @@ class Git(FetchMethod):
def try_premirror(self, ud, d):
# If we don't do this, updating an existing checkout with only premirrors
# is not possible
if d.getVar("BB_FETCH_PREMIRRORONLY") is not None:
if d.getVar("BB_FETCH_PREMIRRORONLY", True) is not None:
return True
if os.path.exists(ud.clonedir):
return False
@@ -322,18 +238,10 @@ class Git(FetchMethod):
def download(self, ud, d):
"""Fetch url"""
no_clone = not os.path.exists(ud.clonedir)
need_update = no_clone or self.need_update(ud, d)
# A current clone is preferred to either tarball, a shallow tarball is
# preferred to an out of date clone, and a missing clone will use
# either tarball.
if ud.shallow and os.path.exists(ud.fullshallow) and need_update:
ud.localpath = ud.fullshallow
return
elif os.path.exists(ud.fullmirror) and no_clone:
# If the checkout doesn't exist and the mirror tarball does, extract it
if not os.path.exists(ud.clonedir) and os.path.exists(ud.fullmirror):
bb.utils.mkdirhier(ud.clonedir)
runfetchcmd("tar -xzf %s" % ud.fullmirror, d, workdir=ud.clonedir)
runfetchcmd("tar -xzf %s" % (ud.fullmirror), d, workdir=ud.clonedir)
repourl = self._get_repo_url(ud)
@@ -344,7 +252,7 @@ class Git(FetchMethod):
repourl = repourl[7:]
clone_cmd = "LANG=C %s clone --bare --mirror %s %s --progress" % (ud.basecmd, repourl, ud.clonedir)
if ud.proto.lower() != 'file':
bb.fetch2.check_network_access(d, clone_cmd, ud.url)
bb.fetch2.check_network_access(d, clone_cmd)
progresshandler = GitProgressHandler(d)
runfetchcmd(clone_cmd, d, log=progresshandler)
@@ -366,7 +274,6 @@ class Git(FetchMethod):
progresshandler = GitProgressHandler(d)
runfetchcmd(fetch_cmd, d, log=progresshandler, workdir=ud.clonedir)
runfetchcmd("%s prune-packed" % ud.basecmd, d, workdir=ud.clonedir)
runfetchcmd("%s pack-refs --all" % ud.basecmd, d, workdir=ud.clonedir)
runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d, workdir=ud.clonedir)
try:
os.unlink(ud.fullmirror)
@@ -378,90 +285,22 @@ class Git(FetchMethod):
raise bb.fetch2.FetchError("Unable to find revision %s in branch %s even from upstream" % (ud.revisions[name], ud.branches[name]))
def build_mirror_data(self, ud, d):
if ud.shallow and ud.write_shallow_tarballs:
if not os.path.exists(ud.fullshallow):
if os.path.islink(ud.fullshallow):
os.unlink(ud.fullshallow)
tempdir = tempfile.mkdtemp(dir=d.getVar('DL_DIR'))
shallowclone = os.path.join(tempdir, 'git')
try:
self.clone_shallow_local(ud, shallowclone, d)
logger.info("Creating tarball of git repository")
runfetchcmd("tar -czf %s ." % ud.fullshallow, d, workdir=shallowclone)
runfetchcmd("touch %s.done" % ud.fullshallow, d)
finally:
bb.utils.remove(tempdir, recurse=True)
elif ud.write_tarballs and not os.path.exists(ud.fullmirror):
# Generate a mirror tarball if needed
if ud.write_tarballs and not os.path.exists(ud.fullmirror):
# it's possible that this symlink points to read-only filesystem with PREMIRROR
if os.path.islink(ud.fullmirror):
os.unlink(ud.fullmirror)
logger.info("Creating tarball of git repository")
runfetchcmd("tar -czf %s ." % ud.fullmirror, d, workdir=ud.clonedir)
runfetchcmd("touch %s.done" % ud.fullmirror, d)
def clone_shallow_local(self, ud, dest, d):
"""Clone the repo and make it shallow.
The upstream url of the new clone isn't set at this time, as it'll be
set correctly when unpacked."""
runfetchcmd("%s clone %s %s %s" % (ud.basecmd, ud.cloneflags, ud.clonedir, dest), d)
to_parse, shallow_branches = [], []
for name in ud.names:
revision = ud.revisions[name]
depth = ud.shallow_depths[name]
if depth:
to_parse.append('%s~%d^{}' % (revision, depth - 1))
# For nobranch, we need a ref, otherwise the commits will be
# removed, and for non-nobranch, we truncate the branch to our
# srcrev, to avoid keeping unnecessary history beyond that.
branch = ud.branches[name]
if ud.nobranch:
ref = "refs/shallow/%s" % name
elif ud.bareclone:
ref = "refs/heads/%s" % branch
else:
ref = "refs/remotes/origin/%s" % branch
shallow_branches.append(ref)
runfetchcmd("%s update-ref %s %s" % (ud.basecmd, ref, revision), d, workdir=dest)
# Map srcrev+depths to revisions
parsed_depths = runfetchcmd("%s rev-parse %s" % (ud.basecmd, " ".join(to_parse)), d, workdir=dest)
# Resolve specified revisions
parsed_revs = runfetchcmd("%s rev-parse %s" % (ud.basecmd, " ".join('"%s^{}"' % r for r in ud.shallow_revs)), d, workdir=dest)
shallow_revisions = parsed_depths.splitlines() + parsed_revs.splitlines()
# Apply extra ref wildcards
all_refs = runfetchcmd('%s for-each-ref "--format=%%(refname)"' % ud.basecmd,
d, workdir=dest).splitlines()
for r in ud.shallow_extra_refs:
if not ud.bareclone:
r = r.replace('refs/heads/', 'refs/remotes/origin/')
if '*' in r:
matches = filter(lambda a: fnmatch.fnmatchcase(a, r), all_refs)
shallow_branches.extend(matches)
else:
shallow_branches.append(r)
# Make the repository shallow
shallow_cmd = [self.make_shallow_path, '-s']
for b in shallow_branches:
shallow_cmd.append('-r')
shallow_cmd.append(b)
shallow_cmd.extend(shallow_revisions)
runfetchcmd(subprocess.list2cmdline(shallow_cmd), d, workdir=dest)
runfetchcmd("tar -czf %s %s" % (ud.fullmirror, os.path.join(".") ), d, workdir=ud.clonedir)
runfetchcmd("touch %s.done" % (ud.fullmirror), d, workdir=ud.clonedir)
def unpack(self, ud, destdir, d):
""" unpack the downloaded src to destdir"""
subdir = ud.parm.get("subpath", "")
if subdir != "":
readpathspec = ":%s" % subdir
readpathspec = ":%s" % (subdir)
def_destsuffix = "%s/" % os.path.basename(subdir.rstrip('/'))
else:
readpathspec = ""
@@ -472,12 +311,11 @@ class Git(FetchMethod):
if os.path.exists(destdir):
bb.utils.prunedir(destdir)
if ud.shallow and (not os.path.exists(ud.clonedir) or self.need_update(ud, d)):
bb.utils.mkdirhier(destdir)
runfetchcmd("tar -xzf %s" % ud.fullshallow, d, workdir=destdir)
else:
runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, ud.cloneflags, ud.clonedir, destdir), d)
cloneflags = "-s -n"
if ud.bareclone:
cloneflags += " --mirror"
runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, ud.clonedir, destdir), d)
repourl = self._get_repo_url(ud)
runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, repourl), d, workdir=destdir)
if not ud.nocheckout:
@@ -489,7 +327,7 @@ class Git(FetchMethod):
branchname = ud.branches[ud.names[0]]
runfetchcmd("%s checkout -B %s %s" % (ud.basecmd, branchname, \
ud.revisions[ud.names[0]]), d, workdir=destdir)
runfetchcmd("%s branch %s --set-upstream-to origin/%s" % (ud.basecmd, branchname, \
runfetchcmd("%s branch --set-upstream %s origin/%s" % (ud.basecmd, branchname, \
branchname), d, workdir=destdir)
else:
runfetchcmd("%s checkout %s" % (ud.basecmd, ud.revisions[ud.names[0]]), d, workdir=destdir)
@@ -542,26 +380,14 @@ class Git(FetchMethod):
"""
Run git ls-remote with the specified search string
"""
# Prevent recursion e.g. in OE if SRCPV is in PV, PV is in WORKDIR,
# and WORKDIR is in PATH (as a result of RSS), our call to
# runfetchcmd() exports PATH so this function will get called again (!)
# In this scenario the return call of the function isn't actually
# important - WORKDIR isn't needed in PATH to call git ls-remote
# anyway.
if d.getVar('_BB_GIT_IN_LSREMOTE', False):
return ''
d.setVar('_BB_GIT_IN_LSREMOTE', '1')
try:
repourl = self._get_repo_url(ud)
cmd = "%s ls-remote %s %s" % \
(ud.basecmd, repourl, search)
if ud.proto.lower() != 'file':
bb.fetch2.check_network_access(d, cmd, repourl)
output = runfetchcmd(cmd, d, True)
if not output:
raise bb.fetch2.FetchError("The command %s gave empty output unexpectedly" % cmd, ud.url)
finally:
d.delVar('_BB_GIT_IN_LSREMOTE')
repourl = self._get_repo_url(ud)
cmd = "%s ls-remote %s %s" % \
(ud.basecmd, repourl, search)
if ud.proto.lower() != 'file':
bb.fetch2.check_network_access(d, cmd)
output = runfetchcmd(cmd, d, True)
if not output:
raise bb.fetch2.FetchError("The command %s gave empty output unexpectedly" % cmd, ud.url)
return output
def _latest_revision(self, ud, d, name):
@@ -592,11 +418,10 @@ class Git(FetchMethod):
"""
pupver = ('', '')
tagregex = re.compile(d.getVar('UPSTREAM_CHECK_GITTAGREGEX') or "(?P<pver>([0-9][\.|_]?)+)")
tagregex = re.compile(d.getVar('UPSTREAM_CHECK_GITTAGREGEX', True) or "(?P<pver>([0-9][\.|_]?)+)")
try:
output = self._lsremote(ud, d, "refs/tags/*")
except (bb.fetch2.FetchError, bb.fetch2.NetworkAccess) as e:
bb.note("Could not list remote: %s" % str(e))
except bb.fetch2.FetchError or bb.fetch2.NetworkAccess:
return pupver
verstring = ""
@@ -645,7 +470,7 @@ class Git(FetchMethod):
if not os.path.exists(rev_file) or not os.path.getsize(rev_file):
from pipes import quote
commits = bb.fetch2.runfetchcmd(
"git rev-list %s -- | wc -l" % quote(rev),
"git rev-list %s -- | wc -l" % (quote(rev)),
d, quiet=True).strip().lstrip('0')
if commits:
open(rev_file, "w").write("%d\n" % int(commits))
@@ -660,5 +485,5 @@ class Git(FetchMethod):
try:
self._lsremote(ud, d, "")
return True
except bb.fetch2.FetchError:
except FetchError:
return False

View File

@@ -22,6 +22,7 @@ BitBake 'Fetch' git annex implementation
import os
import bb
from bb import data
from bb.fetch2.git import Git
from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
@@ -33,11 +34,6 @@ class GitANNEX(Git):
"""
return ud.type in ['gitannex']
def urldata_init(self, ud, d):
super(GitANNEX, self).urldata_init(ud, d)
if ud.shallow:
ud.shallow_extra_refs += ['refs/heads/git-annex', 'refs/heads/synced/*']
def uses_annex(self, ud, d, wd):
for name in ud.names:
try:
@@ -60,21 +56,9 @@ class GitANNEX(Git):
def download(self, ud, d):
Git.download(self, ud, d)
if not ud.shallow or ud.localpath != ud.fullshallow:
if self.uses_annex(ud, d, ud.clonedir):
self.update_annex(ud, d, ud.clonedir)
def clone_shallow_local(self, ud, dest, d):
super(GitANNEX, self).clone_shallow_local(ud, dest, d)
try:
runfetchcmd("%s annex init" % ud.basecmd, d, workdir=dest)
except bb.fetch.FetchError:
pass
if self.uses_annex(ud, d, dest):
runfetchcmd("%s annex get" % ud.basecmd, d, workdir=dest)
runfetchcmd("chmod u+w -R %s/.git/annex" % (dest), d, quiet=True, workdir=dest)
annex = self.uses_annex(ud, d, ud.clonedir)
if annex:
self.update_annex(ud, d, ud.clonedir)
def unpack(self, ud, destdir, d):
Git.unpack(self, ud, destdir, d)

View File

@@ -31,6 +31,7 @@ NOTE: Switching a SRC_URI from "git://" to "gitsm://" requires a clean of your r
import os
import bb
from bb import data
from bb.fetch2.git import Git
from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
@@ -107,7 +108,7 @@ class GitSM(Git):
os.rename(ud.clonedir, gitdir)
runfetchcmd("sed " + gitdir + "/config -i -e 's/bare.*=.*true/bare = false/'", d)
runfetchcmd(ud.basecmd + " reset --hard", d, workdir=tmpclonedir)
runfetchcmd(ud.basecmd + " checkout -f " + ud.revisions[ud.names[0]], d, workdir=tmpclonedir)
runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d, workdir=tmpclonedir)
runfetchcmd(ud.basecmd + " submodule update --init --recursive", d, workdir=tmpclonedir)
self._set_relative_paths(tmpclonedir)
runfetchcmd("sed " + gitdir + "/config -i -e 's/bare.*=.*false/bare = true/'", d, workdir=tmpclonedir)
@@ -117,19 +118,14 @@ class GitSM(Git):
def download(self, ud, d):
Git.download(self, ud, d)
if not ud.shallow or ud.localpath != ud.fullshallow:
submodules = self.uses_submodules(ud, d, ud.clonedir)
if submodules:
self.update_submodules(ud, d)
def clone_shallow_local(self, ud, dest, d):
super(GitSM, self).clone_shallow_local(ud, dest, d)
runfetchcmd('cp -fpPRH "%s/modules" "%s/"' % (ud.clonedir, os.path.join(dest, '.git')), d)
submodules = self.uses_submodules(ud, d, ud.clonedir)
if submodules:
self.update_submodules(ud, d)
def unpack(self, ud, destdir, d):
Git.unpack(self, ud, destdir, d)
if self.uses_submodules(ud, d, ud.destdir):
submodules = self.uses_submodules(ud, d, ud.destdir)
if submodules:
runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d, workdir=ud.destdir)
runfetchcmd(ud.basecmd + " submodule update --init --recursive", d, workdir=ud.destdir)

View File

@@ -29,6 +29,7 @@ import sys
import logging
import bb
import errno
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import MissingParameterError
@@ -66,7 +67,7 @@ class Hg(FetchMethod):
else:
ud.proto = "hg"
ud.setup_revisions(d)
ud.setup_revisons(d)
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
@@ -76,17 +77,16 @@ class Hg(FetchMethod):
# Create paths to mercurial checkouts
hgsrcname = '%s_%s_%s' % (ud.module.replace('/', '.'), \
ud.host, ud.path.replace('/', '.'))
mirrortarball = 'hg_%s.tar.gz' % hgsrcname
ud.fullmirror = os.path.join(d.getVar("DL_DIR"), mirrortarball)
ud.mirrortarballs = [mirrortarball]
ud.mirrortarball = 'hg_%s.tar.gz' % hgsrcname
ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
hgdir = d.getVar("HGDIR") or (d.getVar("DL_DIR") + "/hg/")
hgdir = d.getVar("HGDIR", True) or (d.getVar("DL_DIR", True) + "/hg/")
ud.pkgdir = os.path.join(hgdir, hgsrcname)
ud.moddir = os.path.join(ud.pkgdir, ud.module)
ud.localfile = ud.moddir
ud.basecmd = d.getVar("FETCHCMD_hg") or "/usr/bin/env hg"
ud.basecmd = data.getVar("FETCHCMD_hg", d, True) or "/usr/bin/env hg"
ud.write_tarballs = d.getVar("BB_GENERATE_MIRROR_TARBALLS")
ud.write_tarballs = d.getVar("BB_GENERATE_MIRROR_TARBALLS", True)
def need_update(self, ud, d):
revTag = ud.parm.get('rev', 'tip')
@@ -99,7 +99,7 @@ class Hg(FetchMethod):
def try_premirror(self, ud, d):
# If we don't do this, updating an existing checkout with only premirrors
# is not possible
if d.getVar("BB_FETCH_PREMIRRORONLY") is not None:
if d.getVar("BB_FETCH_PREMIRRORONLY", True) is not None:
return True
if os.path.exists(ud.moddir):
return False
@@ -221,7 +221,7 @@ class Hg(FetchMethod):
"""
Compute tip revision for the url
"""
bb.fetch2.check_network_access(d, self._buildhgcommand(ud, d, "info"), ud.url)
bb.fetch2.check_network_access(d, self._buildhgcommand(ud, d, "info"))
output = runfetchcmd(self._buildhgcommand(ud, d, "info"), d)
return output.strip()

View File

@@ -29,6 +29,7 @@ import os
import urllib.request, urllib.parse, urllib.error
import bb
import bb.utils
from bb import data
from bb.fetch2 import FetchMethod, FetchError
from bb.fetch2 import logger
@@ -62,11 +63,17 @@ class Local(FetchMethod):
newpath = path
if path[0] == "/":
return [path]
filespath = d.getVar('FILESPATH')
filespath = data.getVar('FILESPATH', d, True)
if filespath:
logger.debug(2, "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:
filesdir = data.getVar('FILESDIR', d, True)
if filesdir:
logger.debug(2, "Searching for %s in path: %s" % (path, filesdir))
newpath = os.path.join(filesdir, path)
searched.append(newpath)
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)
@@ -74,7 +81,7 @@ class Local(FetchMethod):
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)
dldirfile = os.path.join(d.getVar("DL_DIR", True), path)
logger.debug(2, "Defaulting to %s for %s" % (dldirfile, path))
bb.utils.mkdirhier(os.path.dirname(dldirfile))
searched.append(dldirfile)
@@ -93,10 +100,13 @@ class Local(FetchMethod):
# no need to fetch local files, we'll deal with them in place.
if self.supports_checksum(urldata) and not os.path.exists(urldata.localpath):
locations = []
filespath = d.getVar('FILESPATH')
filespath = data.getVar('FILESPATH', d, True)
if filespath:
locations = filespath.split(":")
locations.append(d.getVar("DL_DIR"))
filesdir = data.getVar('FILESDIR', d, True)
if filesdir:
locations.append(filesdir)
locations.append(d.getVar("DL_DIR", True))
msg = "Unable to find file " + urldata.url + " anywhere. The paths that were searched were:\n " + "\n ".join(locations)
raise FetchError(msg)

View File

@@ -25,6 +25,7 @@ import json
import subprocess
import signal
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import ChecksumError
@@ -32,6 +33,7 @@ from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
from bb.fetch2 import UnpackError
from bb.fetch2 import ParameterError
from distutils import spawn
def subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
@@ -78,7 +80,6 @@ class Npm(FetchMethod):
if not ud.version:
raise ParameterError("NPM fetcher requires a version parameter", ud.url)
ud.bbnpmmanifest = "%s-%s.deps.json" % (ud.pkgname, ud.version)
ud.bbnpmmanifest = ud.bbnpmmanifest.replace('/', '-')
ud.registry = "http://%s" % (ud.url.replace('npm://', '', 1).split(';'))[0]
prefixdir = "npm/%s" % ud.pkgname
ud.pkgdatadir = d.expand("${DL_DIR}/%s" % prefixdir)
@@ -86,14 +87,12 @@ class Npm(FetchMethod):
bb.utils.mkdirhier(ud.pkgdatadir)
ud.localpath = d.expand("${DL_DIR}/npm/%s" % ud.bbnpmmanifest)
self.basecmd = d.getVar("FETCHCMD_wget") or "/usr/bin/env wget -O -t 2 -T 30 -nv --passive-ftp --no-check-certificate "
self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -O -t 2 -T 30 -nv --passive-ftp --no-check-certificate "
ud.prefixdir = prefixdir
ud.write_tarballs = ((d.getVar("BB_GENERATE_MIRROR_TARBALLS") or "0") != "0")
mirrortarball = 'npm_%s-%s.tar.xz' % (ud.pkgname, ud.version)
mirrortarball = mirrortarball.replace('/', '-')
ud.fullmirror = os.path.join(d.getVar("DL_DIR"), mirrortarball)
ud.mirrortarballs = [mirrortarball]
ud.write_tarballs = ((data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) or "0") != "0")
ud.mirrortarball = 'npm_%s-%s.tar.xz' % (ud.pkgname, ud.version)
ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
def need_update(self, ud, d):
if os.path.exists(ud.localpath):
@@ -102,8 +101,8 @@ class Npm(FetchMethod):
def _runwget(self, ud, d, command, quiet):
logger.debug(2, "Fetching %s using command '%s'" % (ud.url, command))
bb.fetch2.check_network_access(d, command, ud.url)
dldir = d.getVar("DL_DIR")
bb.fetch2.check_network_access(d, command)
dldir = d.getVar("DL_DIR", True)
runfetchcmd(command, d, quiet, workdir=dldir)
def _unpackdep(self, ud, pkg, data, destdir, dldir, d):
@@ -117,7 +116,7 @@ class Npm(FetchMethod):
# Change to subdir before executing command
if not os.path.exists(destdir):
os.makedirs(destdir)
path = d.getVar('PATH')
path = d.getVar('PATH', True)
if path:
cmd = "PATH=\"%s\" %s" % (path, cmd)
bb.note("Unpacking %s to %s/" % (file, destdir))
@@ -133,8 +132,9 @@ class Npm(FetchMethod):
def unpack(self, ud, destdir, d):
dldir = d.getVar("DL_DIR")
with open("%s/npm/%s" % (dldir, ud.bbnpmmanifest)) as datafile:
dldir = d.getVar("DL_DIR", True)
depdumpfile = "%s-%s.deps.json" % (ud.pkgname, ud.version)
with open("%s/npm/%s" % (dldir, depdumpfile)) as datafile:
workobj = json.load(datafile)
dldir = "%s/%s" % (os.path.dirname(ud.localpath), ud.pkgname)
@@ -182,27 +182,19 @@ class Npm(FetchMethod):
if pkg_os:
if not isinstance(pkg_os, list):
pkg_os = [pkg_os]
blacklist = False
for item in pkg_os:
if item.startswith('!'):
blacklist = True
break
if (not blacklist and 'linux' not in pkg_os) or '!linux' in pkg_os:
if 'linux' not in pkg_os or '!linux' in pkg_os:
logger.debug(2, "Skipping %s since it's incompatible with Linux" % pkg)
return
#logger.debug(2, "Output URL is %s - %s - %s" % (ud.basepath, ud.basename, ud.localfile))
outputurl = pdata['dist']['tarball']
data[pkg] = {}
data[pkg]['tgz'] = os.path.basename(outputurl)
if outputurl in fetchedlist:
return
self._runwget(ud, d, "%s --directory-prefix=%s %s" % (self.basecmd, ud.prefixdir, outputurl), False)
fetchedlist.append(outputurl)
if not outputurl in fetchedlist:
self._runwget(ud, d, "%s --directory-prefix=%s %s" % (self.basecmd, ud.prefixdir, outputurl), False)
fetchedlist.append(outputurl)
dependencies = pdata.get('dependencies', {})
optionalDependencies = pdata.get('optionalDependencies', {})
dependencies.update(optionalDependencies)
depsfound = {}
optdepsfound = {}
data[pkg]['deps'] = {}
@@ -259,32 +251,25 @@ class Npm(FetchMethod):
lockdown = {}
if not os.listdir(ud.pkgdatadir) and os.path.exists(ud.fullmirror):
dest = d.getVar("DL_DIR")
dest = d.getVar("DL_DIR", True)
bb.utils.mkdirhier(dest)
runfetchcmd("tar -xJf %s" % (ud.fullmirror), d, workdir=dest)
return
if ud.parm.get("noverify", None) != '1':
shwrf = d.getVar('NPM_SHRINKWRAP')
logger.debug(2, "NPM shrinkwrap file is %s" % shwrf)
if shwrf:
try:
with open(shwrf) as datafile:
shrinkobj = json.load(datafile)
except Exception as e:
raise FetchError('Error loading NPM_SHRINKWRAP file "%s" for %s: %s' % (shwrf, ud.pkgname, str(e)))
elif not ud.ignore_checksums:
logger.warning('Missing shrinkwrap file in NPM_SHRINKWRAP for %s, this will lead to unreliable builds!' % ud.pkgname)
lckdf = d.getVar('NPM_LOCKDOWN')
logger.debug(2, "NPM lockdown file is %s" % lckdf)
if lckdf:
try:
with open(lckdf) as datafile:
lockdown = json.load(datafile)
except Exception as e:
raise FetchError('Error loading NPM_LOCKDOWN file "%s" for %s: %s' % (lckdf, ud.pkgname, str(e)))
elif not ud.ignore_checksums:
logger.warning('Missing lockdown file in NPM_LOCKDOWN for %s, this will lead to unreproducible builds!' % ud.pkgname)
shwrf = d.getVar('NPM_SHRINKWRAP', True)
logger.debug(2, "NPM shrinkwrap file is %s" % shwrf)
try:
with open(shwrf) as datafile:
shrinkobj = json.load(datafile)
except:
logger.warning('Missing shrinkwrap file in NPM_SHRINKWRAP for %s, this will lead to unreliable builds!' % ud.pkgname)
lckdf = d.getVar('NPM_LOCKDOWN', True)
logger.debug(2, "NPM lockdown file is %s" % lckdf)
try:
with open(lckdf) as datafile:
lockdown = json.load(datafile)
except:
logger.warning('Missing lockdown file in NPM_LOCKDOWN for %s, this will lead to unreproducible builds!' % ud.pkgname)
if ('name' not in shrinkobj):
self._getdependencies(ud.pkgname, jsondepobj, ud.version, d, ud)
@@ -301,7 +286,7 @@ class Npm(FetchMethod):
if os.path.islink(ud.fullmirror):
os.unlink(ud.fullmirror)
dldir = d.getVar("DL_DIR")
dldir = d.getVar("DL_DIR", True)
logger.info("Creating tarball of npm data")
runfetchcmd("tar -cJf %s npm/%s npm/%s" % (ud.fullmirror, ud.bbnpmmanifest, ud.pkgname), d,
workdir=dldir)

View File

@@ -10,6 +10,7 @@ import os
import sys
import logging
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import MissingParameterError
@@ -33,7 +34,7 @@ class Osc(FetchMethod):
# Create paths to osc checkouts
relpath = self._strip_leading_slashes(ud.path)
ud.pkgdir = os.path.join(d.getVar('OSCDIR'), ud.host)
ud.pkgdir = os.path.join(d.getVar('OSCDIR', True), ud.host)
ud.moddir = os.path.join(ud.pkgdir, relpath, ud.module)
if 'rev' in ud.parm:
@@ -46,7 +47,7 @@ class Osc(FetchMethod):
else:
ud.revision = ""
ud.localfile = d.expand('%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.path.replace('/', '.'), ud.revision))
ud.localfile = data.expand('%s_%s_%s.tar.gz' % (ud.module.replace('/', '.'), ud.path.replace('/', '.'), ud.revision), d)
def _buildosccommand(self, ud, d, command):
"""
@@ -54,7 +55,7 @@ class Osc(FetchMethod):
command is "fetch", "update", "info"
"""
basecmd = d.expand('${FETCHCMD_osc}')
basecmd = data.expand('${FETCHCMD_osc}', d)
proto = ud.parm.get('protocol', 'ocs')
@@ -83,7 +84,7 @@ class Osc(FetchMethod):
logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
if os.access(os.path.join(d.getVar('OSCDIR'), ud.path, ud.module), os.R_OK):
if os.access(os.path.join(d.getVar('OSCDIR', True), ud.path, ud.module), os.R_OK):
oscupdatecmd = self._buildosccommand(ud, d, "update")
logger.info("Update "+ ud.url)
# update sources there
@@ -111,7 +112,7 @@ class Osc(FetchMethod):
Generate a .oscrc to be used for this run.
"""
config_path = os.path.join(d.getVar('OSCDIR'), "oscrc")
config_path = os.path.join(d.getVar('OSCDIR', True), "oscrc")
if (os.path.exists(config_path)):
os.remove(config_path)
@@ -120,8 +121,8 @@ class Osc(FetchMethod):
f.write("apisrv = %s\n" % ud.host)
f.write("scheme = http\n")
f.write("su-wrapper = su -c\n")
f.write("build-root = %s\n" % d.getVar('WORKDIR'))
f.write("urllist = %s\n" % d.getVar("OSCURLLIST"))
f.write("build-root = %s\n" % d.getVar('WORKDIR', True))
f.write("urllist = %s\n" % d.getVar("OSCURLLIST", True))
f.write("extra-pkgs = gzip\n")
f.write("\n")
f.write("[%s]\n" % ud.host)

View File

@@ -26,6 +26,7 @@ BitBake 'Fetch' implementation for perforce
import os
import logging
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import logger
@@ -43,13 +44,13 @@ class Perforce(FetchMethod):
provided by the env, use it. If P4PORT is specified by the recipe, use
its values, which may override the settings in P4CONFIG.
"""
ud.basecmd = d.getVar('FETCHCMD_p4')
ud.basecmd = d.getVar('FETCHCMD_p4', True)
if not ud.basecmd:
ud.basecmd = "/usr/bin/env p4"
ud.dldir = d.getVar('P4DIR')
ud.dldir = d.getVar('P4DIR', True)
if not ud.dldir:
ud.dldir = '%s/%s' % (d.getVar('DL_DIR'), 'p4')
ud.dldir = '%s/%s' % (d.getVar('DL_DIR', True), 'p4')
path = ud.url.split('://')[1]
path = path.split(';')[0]
@@ -61,7 +62,7 @@ class Perforce(FetchMethod):
ud.path = path
ud.usingp4config = False
p4port = d.getVar('P4PORT')
p4port = d.getVar('P4PORT', True)
if p4port:
logger.debug(1, 'Using recipe provided P4PORT: %s' % p4port)
@@ -70,7 +71,7 @@ class Perforce(FetchMethod):
logger.debug(1, '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)
bb.fetch2.check_network_access(d, p4cmd)
ud.host = runfetchcmd(p4cmd, d, True)
ud.host = ud.host.split(': ')[1].strip()
logger.debug(1, 'Determined P4PORT to be: %s' % ud.host)
@@ -86,9 +87,9 @@ class Perforce(FetchMethod):
cleanedhost = ud.host.replace(':', '.')
ud.pkgdir = os.path.join(ud.dldir, cleanedhost, cleanedpath)
ud.setup_revisions(d)
ud.setup_revisons(d)
ud.localfile = d.expand('%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, ud.revision))
ud.localfile = data.expand('%s_%s_%s.tar.gz' % (cleanedhost, cleanedpath, ud.revision), d)
def _buildp4command(self, ud, d, command, depot_filename=None):
"""
@@ -139,7 +140,7 @@ class Perforce(FetchMethod):
'p4 files' command, including trailing '#rev' file revision indicator
"""
p4cmd = self._buildp4command(ud, d, 'files')
bb.fetch2.check_network_access(d, p4cmd, ud.url)
bb.fetch2.check_network_access(d, p4cmd)
p4fileslist = runfetchcmd(p4cmd, d, True)
p4fileslist = [f.rstrip() for f in p4fileslist.splitlines()]
@@ -170,7 +171,7 @@ class Perforce(FetchMethod):
for afile in filelist:
p4fetchcmd = self._buildp4command(ud, d, 'print', afile)
bb.fetch2.check_network_access(d, p4fetchcmd, ud.url)
bb.fetch2.check_network_access(d, p4fetchcmd)
runfetchcmd(p4fetchcmd, d, workdir=ud.pkgdir)
runfetchcmd('tar -czf %s p4' % (ud.localpath), d, cleanup=[ud.localpath], workdir=ud.pkgdir)
@@ -190,7 +191,7 @@ class Perforce(FetchMethod):
def _latest_revision(self, ud, d, name):
""" Return the latest upstream scm revision number """
p4cmd = self._buildp4command(ud, d, "changes")
bb.fetch2.check_network_access(d, p4cmd, ud.url)
bb.fetch2.check_network_access(d, p4cmd)
tip = runfetchcmd(p4cmd, d, True)
if not tip:

View File

@@ -25,9 +25,9 @@ BitBake "Fetch" repo (git) implementation
import os
import bb
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import runfetchcmd
from bb.fetch2 import logger
class Repo(FetchMethod):
"""Class to fetch a module or modules from repo (git) repositories"""
@@ -51,17 +51,17 @@ class Repo(FetchMethod):
if not ud.manifest.endswith('.xml'):
ud.manifest += '.xml'
ud.localfile = d.expand("repo_%s%s_%s_%s.tar.gz" % (ud.host, ud.path.replace("/", "."), ud.manifest, ud.branch))
ud.localfile = data.expand("repo_%s%s_%s_%s.tar.gz" % (ud.host, ud.path.replace("/", "."), ud.manifest, ud.branch), d)
def download(self, ud, d):
"""Fetch url"""
if os.access(os.path.join(d.getVar("DL_DIR"), ud.localfile), os.R_OK):
if os.access(os.path.join(data.getVar("DL_DIR", d, True), ud.localfile), os.R_OK):
logger.debug(1, "%s already exists (or was stashed). Skipping repo init / sync.", ud.localpath)
return
gitsrcname = "%s%s" % (ud.host, ud.path.replace("/", "."))
repodir = d.getVar("REPODIR") or os.path.join(d.getVar("DL_DIR"), "repo")
repodir = data.getVar("REPODIR", d, True) or os.path.join(data.getVar("DL_DIR", d, True), "repo")
codir = os.path.join(repodir, gitsrcname, ud.manifest)
if ud.user:

View File

@@ -1,98 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake 'Fetch' implementation for Amazon AWS S3.
Class for fetching files from Amazon S3 using the AWS Command Line Interface.
The aws tool must be correctly installed and configured prior to use.
"""
# Copyright (C) 2017, Andre McCurdy <armccurdy@gmail.com>
#
# Based in part on bb.fetch2.wget:
# Copyright (C) 2003, 2004 Chris Larson
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
import os
import bb
import urllib.request, urllib.parse, urllib.error
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import runfetchcmd
class S3(FetchMethod):
"""Class to fetch urls via 'aws s3'"""
def supports(self, ud, d):
"""
Check to see if a given url can be fetched with s3.
"""
return ud.type in ['s3']
def recommends_checksum(self, urldata):
return True
def urldata_init(self, ud, d):
if 'downloadfilename' in ud.parm:
ud.basename = ud.parm['downloadfilename']
else:
ud.basename = os.path.basename(ud.path)
ud.localfile = d.expand(urllib.parse.unquote(ud.basename))
ud.basecmd = d.getVar("FETCHCMD_s3") or "/usr/bin/env aws s3"
def download(self, ud, d):
"""
Fetch urls
Assumes localpath was called first
"""
cmd = '%s cp s3://%s%s %s' % (ud.basecmd, ud.host, ud.path, ud.localpath)
bb.fetch2.check_network_access(d, cmd, ud.url)
runfetchcmd(cmd, d)
# Additional sanity checks copied from the wget class (although there
# are no known issues which mean these are required, treat the aws cli
# tool with a little healthy suspicion).
if not os.path.exists(ud.localpath):
raise FetchError("The aws cp command returned success for s3://%s%s but %s doesn't exist?!" % (ud.host, ud.path, ud.localpath))
if os.path.getsize(ud.localpath) == 0:
os.remove(ud.localpath)
raise FetchError("The aws cp command for s3://%s%s resulted in a zero size file?! Deleting and failing since this isn't right." % (ud.host, ud.path))
return True
def checkstatus(self, fetch, ud, d):
"""
Check the status of a URL
"""
cmd = '%s ls s3://%s%s' % (ud.basecmd, ud.host, ud.path)
bb.fetch2.check_network_access(d, cmd, ud.url)
output = runfetchcmd(cmd, d)
# "aws s3 ls s3://mybucket/foo" will exit with success even if the file
# is not found, so check output of the command to confirm success.
if not output:
raise FetchError("The aws ls command for s3://%s%s gave empty output" % (ud.host, ud.path))
return True

View File

@@ -62,10 +62,12 @@ SRC_URI = "sftp://user@host.example.com/dir/path.file.txt"
import os
import bb
import urllib.request, urllib.parse, urllib.error
from bb import data
from bb.fetch2 import URI
from bb.fetch2 import FetchMethod
from bb.fetch2 import runfetchcmd
class SFTP(FetchMethod):
"""Class to fetch urls via 'sftp'"""
@@ -90,7 +92,7 @@ class SFTP(FetchMethod):
else:
ud.basename = os.path.basename(ud.path)
ud.localfile = d.expand(urllib.parse.unquote(ud.basename))
ud.localfile = data.expand(urllib.parse.unquote(ud.basename), d)
def download(self, ud, d):
"""Fetch urls"""
@@ -102,7 +104,7 @@ class SFTP(FetchMethod):
port = '-P %d' % urlo.port
urlo.port = None
dldir = d.getVar('DL_DIR')
dldir = data.getVar('DL_DIR', d, True)
lpath = os.path.join(dldir, ud.localfile)
user = ''

View File

@@ -43,6 +43,7 @@ IETF secsh internet draft:
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import re, os
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import logger
@@ -86,11 +87,11 @@ class SSH(FetchMethod):
m = __pattern__.match(urldata.url)
path = m.group('path')
host = m.group('host')
urldata.localpath = os.path.join(d.getVar('DL_DIR'),
urldata.localpath = os.path.join(d.getVar('DL_DIR', True),
os.path.basename(os.path.normpath(path)))
def download(self, urldata, d):
dldir = d.getVar('DL_DIR')
dldir = d.getVar('DL_DIR', True)
m = __pattern__.match(urldata.url)
path = m.group('path')

View File

@@ -28,6 +28,7 @@ import sys
import logging
import bb
import re
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import MissingParameterError
@@ -49,7 +50,7 @@ class Svn(FetchMethod):
if not "module" in ud.parm:
raise MissingParameterError('module', ud.url)
ud.basecmd = d.getVar('FETCHCMD_svn')
ud.basecmd = d.getVar('FETCHCMD_svn', True)
ud.module = ud.parm["module"]
@@ -60,15 +61,15 @@ class Svn(FetchMethod):
# Create paths to svn checkouts
relpath = self._strip_leading_slashes(ud.path)
ud.pkgdir = os.path.join(d.expand('${SVNDIR}'), ud.host, relpath)
ud.pkgdir = os.path.join(data.expand('${SVNDIR}', d), ud.host, relpath)
ud.moddir = os.path.join(ud.pkgdir, ud.module)
ud.setup_revisions(d)
ud.setup_revisons(d)
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
ud.localfile = d.expand('%s_%s_%s_%s_.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision))
ud.localfile = data.expand('%s_%s_%s_%s_.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision), d)
def _buildsvncommand(self, ud, d, command):
"""
@@ -78,9 +79,9 @@ class Svn(FetchMethod):
proto = ud.parm.get('protocol', 'svn')
svn_ssh = None
if proto == "svn+ssh" and "ssh" in ud.parm:
svn_ssh = ud.parm["ssh"]
svn_rsh = None
if proto == "svn+ssh" and "rsh" in ud.parm:
svn_rsh = ud.parm["rsh"]
svnroot = ud.host + ud.path
@@ -112,8 +113,8 @@ class Svn(FetchMethod):
else:
raise FetchError("Invalid svn command %s" % command, ud.url)
if svn_ssh:
svncmd = "SVN_SSH=\"%s\" %s" % (svn_ssh, svncmd)
if svn_rsh:
svncmd = "svn_RSH=\"%s\" %s" % (svn_rsh, svncmd)
return svncmd
@@ -172,7 +173,7 @@ class Svn(FetchMethod):
"""
Return the latest upstream revision number
"""
bb.fetch2.check_network_access(d, self._buildsvncommand(ud, d, "log1"), ud.url)
bb.fetch2.check_network_access(d, self._buildsvncommand(ud, d, "log1"))
output = runfetchcmd("LANG=C LC_ALL=C " + self._buildsvncommand(ud, d, "log1"), d, True)

View File

@@ -30,10 +30,10 @@ import tempfile
import subprocess
import os
import logging
import errno
import bb
import bb.progress
import urllib.request, urllib.parse, urllib.error
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import logger
@@ -84,19 +84,19 @@ class Wget(FetchMethod):
else:
ud.basename = os.path.basename(ud.path)
ud.localfile = d.expand(urllib.parse.unquote(ud.basename))
ud.localfile = data.expand(urllib.parse.unquote(ud.basename), d)
if not ud.localfile:
ud.localfile = d.expand(urllib.parse.unquote(ud.host + ud.path).replace("/", "."))
ud.localfile = data.expand(urllib.parse.unquote(ud.host + ud.path).replace("/", "."), d)
self.basecmd = d.getVar("FETCHCMD_wget") or "/usr/bin/env wget -t 2 -T 30 --passive-ftp --no-check-certificate"
self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -t 2 -T 30 --passive-ftp --no-check-certificate"
def _runwget(self, ud, d, command, quiet, workdir=None):
def _runwget(self, ud, d, command, quiet):
progresshandler = WgetProgressHandler(d)
logger.debug(2, "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)
bb.fetch2.check_network_access(d, command)
runfetchcmd(command + ' --progress=dot -v', d, quiet, log=progresshandler)
def download(self, ud, d):
"""Fetch urls"""
@@ -104,12 +104,13 @@ class Wget(FetchMethod):
fetchcmd = self.basecmd
if 'downloadfilename' in ud.parm:
dldir = d.getVar("DL_DIR")
dldir = d.getVar("DL_DIR", True)
bb.utils.mkdirhier(os.path.dirname(dldir + os.sep + ud.localfile))
fetchcmd += " -O " + dldir + os.sep + ud.localfile
if ud.user and ud.pswd:
fetchcmd += " --user=%s --password=%s --auth-no-challenge" % (ud.user, ud.pswd)
if ud.user:
up = ud.user.split(":")
fetchcmd += " --user=%s --password=%s --auth-no-challenge" % (up[0],up[1])
uri = ud.url.split(";")[0]
if os.path.exists(ud.localpath):
@@ -207,21 +208,8 @@ class Wget(FetchMethod):
h.request(req.get_method(), req.selector, req.data, headers)
except socket.error as err: # XXX what error?
# Don't close connection when cache is enabled.
# Instead, try to detect connections that are no longer
# usable (for example, closed unexpectedly) and remove
# them from the cache.
if fetch.connection_cache is None:
h.close()
elif isinstance(err, OSError) and err.errno == errno.EBADF:
# This happens when the server closes the connection despite the Keep-Alive.
# Apparently urllib then uses the file descriptor, expecting it to be
# connected, when in reality the connection is already gone.
# We let the request fail and expect it to be
# tried once more ("try_again" in check_status()),
# with the dead connection removed from the cache.
# If it still fails, we give up, which can happend for bad
# HTTP proxy settings.
fetch.connection_cache.remove_connection(h.host, h.port)
raise urllib.error.URLError(err)
else:
try:
@@ -250,7 +238,6 @@ class Wget(FetchMethod):
return ""
def close(self):
pass
closed = False
resp = addinfourl(fp_dummy(), r.msg, req.get_full_url())
resp.code = r.status
@@ -284,6 +271,11 @@ class Wget(FetchMethod):
"""
http_error_403 = http_error_405
"""
Some servers (e.g. FusionForge) returns 406 Not Acceptable when they
actually mean 405 Method Not Allowed.
"""
http_error_406 = http_error_405
class FixedHTTPRedirectHandler(urllib.request.HTTPRedirectHandler):
"""
@@ -312,29 +304,14 @@ class Wget(FetchMethod):
uri = ud.url.split(";")[0]
r = urllib.request.Request(uri)
r.get_method = lambda: "HEAD"
# Some servers (FusionForge, as used on Alioth) require that the
# optional Accept header is set.
r.add_header("Accept", "*/*")
def add_basic_auth(login_str, request):
'''Adds Basic auth to http request, pass in login:password as string'''
if ud.user:
import base64
encodeuser = base64.b64encode(login_str.encode('utf-8')).decode("utf-8")
encodeuser = base64.b64encode(ud.user.encode('utf-8')).decode("utf-8")
authheader = "Basic %s" % encodeuser
r.add_header("Authorization", authheader)
if ud.user:
add_basic_auth(ud.user, r)
try:
import netrc, urllib.parse
n = netrc.netrc()
login, unused, password = n.authenticators(urllib.parse.urlparse(uri).hostname)
add_basic_auth("%s:%s" % (login, password), r)
except (TypeError, ImportError, IOError, netrc.NetrcParseError):
pass
with opener.open(r) as response:
pass
opener.open(r)
except urllib.error.URLError as e:
if try_again:
logger.debug(2, "checkstatus: trying again")
@@ -421,16 +398,17 @@ class Wget(FetchMethod):
Run fetch checkstatus to get directory information
"""
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 + "'"
try:
self._runwget(ud, d, fetchcmd, True, workdir=workdir)
fetchresult = f.read()
except bb.fetch2.BBFetchException:
fetchresult = ""
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 + "'"
try:
self._runwget(ud, d, fetchcmd, True)
fetchresult = f.read()
except bb.fetch2.BBFetchException:
fetchresult = ""
f.close()
return fetchresult
def _check_latest_version(self, url, package, package_regex, current_version, ud, d):
@@ -557,7 +535,7 @@ class Wget(FetchMethod):
# src.rpm extension was added only for rpm package. Can be removed if the rpm
# packaged will always be considered as having to be manually upgraded
psuffix_regex = "(tar\.gz|tgz|tar\.bz2|zip|xz|tar\.lz|rpm|bz2|orig\.tar\.gz|tar\.xz|src\.tar\.gz|src\.tgz|svnr\d+\.tar\.bz2|stable\.tar\.gz|src\.rpm)"
psuffix_regex = "(tar\.gz|tgz|tar\.bz2|zip|xz|rpm|bz2|orig\.tar\.gz|tar\.xz|src\.tar\.gz|src\.tgz|svnr\d+\.tar\.bz2|stable\.tar\.gz|src\.rpm)"
# match name, version and archive type of a package
package_regex_comp = re.compile("(?P<name>%s?\.?v?)(?P<pver>%s)(?P<arch>%s)?[\.-](?P<type>%s$)"
@@ -565,7 +543,7 @@ class Wget(FetchMethod):
self.suffix_regex_comp = re.compile(psuffix_regex)
# compile regex, can be specific by package or generic regex
pn_regex = d.getVar('UPSTREAM_CHECK_REGEX')
pn_regex = d.getVar('UPSTREAM_CHECK_REGEX', True)
if pn_regex:
package_custom_regex_comp = re.compile(pn_regex)
else:
@@ -586,7 +564,7 @@ class Wget(FetchMethod):
sanity check to ensure same name and type.
"""
package = ud.path.split("/")[-1]
current_version = ['', d.getVar('PV'), '']
current_version = ['', d.getVar('PV', True), '']
"""possible to have no version in pkg name, such as spectrum-fw"""
if not re.search("\d+", package):
@@ -601,7 +579,7 @@ class Wget(FetchMethod):
bb.debug(3, "latest_versionstring, regex: %s" % (package_regex.pattern))
uri = ""
regex_uri = d.getVar("UPSTREAM_CHECK_URI")
regex_uri = d.getVar("UPSTREAM_CHECK_URI", True)
if not regex_uri:
path = ud.path.split(package)[0]
@@ -610,7 +588,7 @@ class Wget(FetchMethod):
dirver_regex = re.compile("(?P<dirver>[^/]*(\d+\.)*\d+([-_]r\d+)*)/")
m = dirver_regex.search(path)
if m:
pn = d.getVar('PN')
pn = d.getVar('PN', True)
dirver = m.group('dirver')
dirver_pn_regex = re.compile("%s\d?" % (re.escape(pn)))

View File

@@ -28,8 +28,6 @@ import logging
import optparse
import warnings
import fcntl
import time
import traceback
import bb
from bb import event
@@ -39,17 +37,11 @@ from bb import ui
from bb import server
from bb import cookerdata
import bb.server.process
import bb.server.xmlrpcclient
logger = logging.getLogger("BitBake")
class BBMainException(Exception):
pass
class BBMainFatal(bb.BBHandledException):
pass
def present_options(optionlist):
if len(optionlist) > 1:
return ' or '.join([', '.join(optionlist[:-1]), optionlist[-1]])
@@ -66,6 +58,9 @@ class BitbakeHelpFormatter(optparse.IndentedHelpFormatter):
if option.dest == 'ui':
valid_uis = list_extension_modules(bb.ui, 'main')
option.help = option.help.replace('@CHOICES@', present_options(valid_uis))
elif option.dest == 'servertype':
valid_server_types = list_extension_modules(bb.server, 'BitBakeServer')
option.help = option.help.replace('@CHOICES@', present_options(valid_server_types))
return optparse.IndentedHelpFormatter.format_option(self, option)
@@ -153,6 +148,11 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
"failed and anything depending on it cannot be built, as much as "
"possible will be built before stopping.")
parser.add_option("-a", "--tryaltconfigs", action="store_true",
dest="tryaltconfigs", default=False,
help="Continue with builds by trying to use alternative providers "
"where possible.")
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).")
@@ -174,24 +174,13 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
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>).")
help="Output more log message data to the terminal.")
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.")
help="Increase the debug level. You can specify this more than once.")
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("-q", "--quiet", action="store_true", dest="quiet", default=False,
help="Output less log message data to the terminal.")
parser.add_option("-n", "--dry-run", action="store_true", dest="dry_run", default=False,
help="Don't execute, just go through the motions.")
@@ -238,6 +227,11 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
default=os.environ.get('BITBAKE_UI', 'knotty'),
help="The user interface to use (@CHOICES@ - default %default).")
# @CHOICES@ is substituted out by BitbakeHelpFormatter above
parser.add_option("-t", "--servertype", action="store", dest="servertype",
default=["process", "xmlrpc"]["BBSERVER" in os.environ],
help="Choose which server type 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 "
@@ -253,14 +247,15 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
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("", "--foreground", action="store_true",
help="Run bitbake server in foreground.")
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("-B", "--bind", action="store", dest="bind", default=False,
help="The name/address for the bitbake server to bind to.")
parser.add_option("-T", "--idle-timeout", type=int,
default=int(os.environ.get("BBTIMEOUT", "0")),
help="Set timeout to unload bitbake server due to inactivity")
parser.add_option("", "--no-setscene", action="store_true",
dest="nosetscene", default=False,
@@ -277,7 +272,7 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
parser.add_option("-m", "--kill-server", action="store_true",
dest="kill_server", default=False,
help="Terminate any running bitbake server.")
help="Terminate the remote server.")
parser.add_option("", "--observe-only", action="store_true",
dest="observe_only", default=False,
@@ -292,13 +287,6 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
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).")
options, targets = parser.parse_args(argv)
if options.quiet and options.verbose:
@@ -320,20 +308,69 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
eventlog = "bitbake_eventlog_%s.json" % datetime.now().strftime("%Y%m%d%H%M%S")
options.writeeventlog = eventlog
if options.bind:
try:
#Checking that the port is a number and is a ':' delimited value
(host, port) = options.bind.split(':')
# if BBSERVER says to autodetect, let's do that
if options.remote_server:
port = -1
if options.remote_server != 'autostart':
host, port = options.remote_server.split(":", 2)
port = int(port)
except (ValueError,IndexError):
raise BBMainException("FATAL: Malformed host:port bind parameter")
options.xmlrpcinterface = (host, port)
else:
options.xmlrpcinterface = (None, 0)
# use automatic port if port set to -1, means read it from
# the bitbake.lock file; this is a bit tricky, but we always expect
# to be in the base of the build directory if we need to have a
# chance to start the server later, anyway
if port == -1:
lock_location = "./bitbake.lock"
# we try to read the address at all times; if the server is not started,
# we'll try to start it after the first connect fails, below
try:
lf = open(lock_location, 'r')
remotedef = lf.readline()
[host, port] = remotedef.split(":")
port = int(port)
lf.close()
options.remote_server = remotedef
except Exception as e:
if options.remote_server != 'autostart':
raise BBMainException("Failed to read bitbake.lock (%s), invalid port" % str(e))
return options, targets[1:]
def start_server(servermodule, configParams, configuration, features):
server = servermodule.BitBakeServer()
single_use = not configParams.server_only and os.getenv('BBSERVER') != 'autostart'
if configParams.bind:
(host, port) = configParams.bind.split(':')
server.initServer((host, int(port)), single_use=single_use,
idle_timeout=configParams.idle_timeout)
configuration.interface = [server.serverImpl.host, server.serverImpl.port]
else:
server.initServer(single_use=single_use)
configuration.interface = []
try:
configuration.setServerRegIdleCallback(server.getServerIdleCB())
cooker = bb.cooker.BBCooker(configuration, features)
server.addcooker(cooker)
server.saveConnectionDetails()
except Exception as e:
while hasattr(server, "event_queue"):
import queue
try:
event = server.event_queue.get(block=False)
except (queue.Empty, IOError):
break
if isinstance(event, logging.LogRecord):
logger.handle(event)
raise
if not configParams.foreground:
server.detach()
cooker.lock.close()
return server
def bitbake_main(configParams, configuration):
# Python multiprocessing requires /dev/shm on Linux
@@ -352,17 +389,51 @@ def bitbake_main(configParams, configuration):
except:
pass
configuration.setConfigParameters(configParams)
if configParams.server_only and configParams.remote_server:
ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
servermodule = import_extension_module(bb.server, configParams.servertype, 'BitBakeServer')
if configParams.server_only:
if configParams.servertype != "xmlrpc":
raise BBMainException("FATAL: If '--server-only' is defined, we must set the "
"servertype as 'xmlrpc'.\n")
if not configParams.bind:
raise BBMainException("FATAL: The '--server-only' option requires a name/address "
"to bind to with the -B option.\n")
else:
try:
#Checking that the port is a number
int(configParams.bind.split(":")[1])
except (ValueError,IndexError):
raise BBMainException(
"FATAL: Malformed host:port bind parameter")
if configParams.remote_server:
raise BBMainException("FATAL: The '--server-only' option conflicts with %s.\n" %
("the BBSERVER environment variable" if "BBSERVER" in os.environ \
else "the '--remote-server' option"))
if configParams.observe_only and not (configParams.remote_server or configParams.bind):
elif configParams.foreground:
raise BBMainException("FATAL: The '--foreground' option can only be used "
"with --server-only.\n")
if configParams.bind and configParams.servertype != "xmlrpc":
raise BBMainException("FATAL: If '-B' or '--bind' is defined, we must "
"set the servertype as 'xmlrpc'.\n")
if configParams.remote_server and configParams.servertype != "xmlrpc":
raise BBMainException("FATAL: If '--remote-server' is defined, we must "
"set the servertype as 'xmlrpc'.\n")
if configParams.observe_only and (not configParams.remote_server or configParams.bind):
raise BBMainException("FATAL: '--observe-only' can only be used by UI clients "
"connecting to a server.\n")
if configParams.kill_server and not configParams.remote_server:
raise BBMainException("FATAL: '--kill-server' can only be used to "
"terminate a remote server")
if "BBDEBUG" in os.environ:
level = int(os.environ["BBDEBUG"])
if level > configuration.debug:
@@ -371,34 +442,6 @@ def bitbake_main(configParams, configuration):
bb.msg.init_msgconfig(configParams.verbose, configuration.debug,
configuration.debug_domains)
server_connection, ui_module = setup_bitbake(configParams, configuration)
# No server connection
if server_connection is None:
if configParams.status_only:
return 1
if configParams.kill_server:
return 0
if not configParams.server_only:
if configParams.status_only:
server_connection.terminate()
return 0
try:
for event in bb.event.ui_queue:
server_connection.events.queue_event(event)
bb.event.ui_queue = []
return ui_module.main(server_connection.connection, server_connection.events,
configParams)
finally:
server_connection.terminate()
else:
return 0
return 1
def setup_bitbake(configParams, configuration, extrafeatures=None):
# Ensure logging messages get sent to the UI as events
handler = bb.event.LogHandler()
if not configParams.status_only:
@@ -408,101 +451,72 @@ def setup_bitbake(configParams, configuration, extrafeatures=None):
# Clear away any spurious environment variables while we stoke up the cooker
cleanedvars = bb.utils.clean_environment()
if configParams.server_only:
featureset = []
ui_module = None
else:
ui_module = import_extension_module(bb.ui, configParams.ui, 'main')
featureset = []
if not configParams.server_only:
# Collect the feature set for the UI
featureset = getattr(ui_module, "featureSet", [])
if extrafeatures:
for feature in extrafeatures:
if not feature in featureset:
featureset.append(feature)
if configParams.server_only:
for param in ('prefile', 'postfile'):
value = getattr(configParams, param)
if value:
setattr(configuration, "%s_server" % param, value)
param = "%s_server" % param
server_connection = None
if configParams.remote_server:
# Connect to a remote XMLRPC server
server_connection = bb.server.xmlrpcclient.connectXMLRPC(configParams.remote_server, featureset,
configParams.observe_only, configParams.xmlrpctoken)
else:
retries = 8
while retries:
try:
topdir, lock = lockBitbake()
sockname = topdir + "/bitbake.sock"
if lock:
if configParams.status_only or configParams.kill_server:
logger.info("bitbake server is not running.")
lock.close()
return None, None
# we start a server with a given configuration
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)
else:
logger.info("Reconnecting to bitbake server...")
if not os.path.exists(sockname):
print("Previous bitbake instance shutting down?, waiting to retry...")
i = 0
lock = None
# Wait for 5s or until we can get the lock
while not lock and i < 50:
time.sleep(0.1)
_, lock = lockBitbake()
i += 1
if lock:
bb.utils.unlockfile(lock)
raise bb.server.process.ProcessTimeout("Bitbake still shutting down as socket exists but no lock?")
if not configParams.server_only:
try:
server_connection = bb.server.process.connectProcessServer(sockname, featureset)
except EOFError:
# The server may have been shutting down but not closed the socket yet. If that happened,
# ignore it.
pass
if server_connection or configParams.server_only:
break
except BBMainFatal:
raise
except (Exception, bb.server.process.ProcessTimeout) as e:
if not retries:
raise
retries -= 1
if isinstance(e, (bb.server.process.ProcessTimeout, BrokenPipeError)):
logger.info("Retrying server connection...")
else:
logger.info("Retrying server connection... (%s)" % traceback.format_exc())
if not retries:
bb.fatal("Unable to connect to bitbake server, or start one")
if retries < 5:
time.sleep(5)
if configParams.kill_server:
server_connection.connection.terminateServer()
server_connection.terminate()
if not configParams.remote_server:
# we start a server with a given configuration
server = start_server(servermodule, configParams, configuration, featureset)
bb.event.ui_queue = []
logger.info("Terminated bitbake server.")
return None, None
else:
if os.getenv('BBSERVER') == 'autostart':
if configParams.remote_server == 'autostart' or \
not servermodule.check_connection(configParams.remote_server, timeout=2):
configParams.bind = 'localhost:0'
srv = start_server(servermodule, configParams, configuration, featureset)
configParams.remote_server = '%s:%d' % tuple(configuration.interface)
bb.event.ui_queue = []
# Restore the environment in case the UI needs it
for k in cleanedvars:
os.environ[k] = cleanedvars[k]
# we start a stub server that is actually a XMLRPClient that connects to a real server
server = servermodule.BitBakeXMLRPCClient(configParams.observe_only,
configParams.xmlrpctoken)
server.saveConnectionDetails(configParams.remote_server)
logger.removeHandler(handler)
return server_connection, ui_module
if not configParams.server_only:
try:
server_connection = server.establishConnection(featureset)
except Exception as e:
bb.fatal("Could not connect to server %s: %s" % (configParams.remote_server, str(e)))
def lockBitbake():
topdir = bb.cookerdata.findTopdir()
if not topdir:
bb.error("Unable to find conf/bblayers.conf or conf/bitbake.conf. BBAPTH is unset and/or not in a build directory?")
raise BBMainFatal
lockfile = topdir + "/bitbake.lock"
return topdir, bb.utils.lockfile(lockfile, False, False)
if configParams.kill_server:
server_connection.connection.terminateServer()
bb.event.ui_queue = []
return 0
server_connection.setupEventQueue()
# Restore the environment in case the UI needs it
for k in cleanedvars:
os.environ[k] = cleanedvars[k]
logger.removeHandler(handler)
if configParams.status_only:
server_connection.terminate()
return 0
try:
return ui_module.main(server_connection.connection, server_connection.events,
configParams)
finally:
bb.event.ui_queue = []
server_connection.terminate()
else:
print("Bitbake server address: %s, server port: %s" % (server.serverImpl.host,
server.serverImpl.port))
if configParams.foreground:
server.serverImpl.serve_forever()
return 0
return 1

View File

@@ -129,7 +129,7 @@ def getDiskData(BBDirs, configuration):
bb.utils.mkdirhier(path)
dev = getMountedDev(path)
# Use path/action as the key
devDict[(path, action)] = [dev, minSpace, minInode]
devDict[os.path.join(path, action)] = [dev, minSpace, minInode]
return devDict
@@ -141,7 +141,7 @@ def getInterval(configuration):
spaceDefault = 50 * 1024 * 1024
inodeDefault = 5 * 1024
interval = configuration.getVar("BB_DISKMON_WARNINTERVAL")
interval = configuration.getVar("BB_DISKMON_WARNINTERVAL", True)
if not interval:
return spaceDefault, inodeDefault
else:
@@ -179,7 +179,7 @@ class diskMonitor:
self.enableMonitor = False
self.configuration = configuration
BBDirs = configuration.getVar("BB_DISKMON_DIRS") or None
BBDirs = configuration.getVar("BB_DISKMON_DIRS", True) or None
if BBDirs:
self.devDict = getDiskData(BBDirs, configuration)
if self.devDict:
@@ -205,21 +205,18 @@ class diskMonitor:
""" Take action for the monitor """
if self.enableMonitor:
diskUsage = {}
for k, attributes in self.devDict.items():
path, action = k
dev, minSpace, minInode = attributes
for k in self.devDict:
path = os.path.dirname(k)
action = os.path.basename(k)
dev = self.devDict[k][0]
minSpace = self.devDict[k][1]
minInode = self.devDict[k][2]
st = os.statvfs(path)
# The available free space, integer number
# The free space, float point number
freeSpace = st.f_bavail * st.f_frsize
# Send all relevant information in the event.
freeSpaceRoot = st.f_bfree * st.f_frsize
totalSpace = st.f_blocks * st.f_frsize
diskUsage[dev] = bb.event.DiskUsageSample(freeSpace, freeSpaceRoot, totalSpace)
if minSpace and freeSpace < minSpace:
# Always show warning, the self.checked would always be False if the action is WARN
if self.preFreeS[k] == 0 or self.preFreeS[k] - freeSpace > self.spaceInterval and not self.checked[k]:
@@ -238,7 +235,7 @@ class diskMonitor:
rq.finish_runqueue(True)
bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, path), self.configuration)
# The free inodes, integer number
# The free inodes, float point number
freeInode = st.f_favail
if minInode and freeInode < minInode:
@@ -263,6 +260,4 @@ class diskMonitor:
self.checked[k] = True
rq.finish_runqueue(True)
bb.event.fire(bb.event.DiskFull(dev, 'inode', freeInode, path), self.configuration)
bb.event.fire(bb.event.MonitorDiskEvent(diskUsage), self.configuration)
return

View File

@@ -201,25 +201,3 @@ def fatal(msgdomain, msg):
logger = logging.getLogger("BitBake")
logger.critical(msg)
sys.exit(1)
def logger_create(name, output=sys.stderr, level=logging.INFO, preserve_handlers=False, color='auto'):
"""Standalone logger creation function"""
logger = logging.getLogger(name)
console = logging.StreamHandler(output)
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
if color == 'always' or (color == 'auto' and output.isatty()):
format.enable_color()
console.setFormatter(format)
if preserve_handlers:
logger.addHandler(console)
else:
logger.handlers = [console]
logger.setLevel(level)
return logger
def has_console_handler(logger):
for handler in logger.handlers:
if isinstance(handler, logging.StreamHandler):
if handler.stream in [sys.stderr, sys.stdout]:
return True
return False

View File

@@ -84,10 +84,6 @@ def update_cache(f):
logger.debug(1, "Updating mtime cache for %s" % f)
update_mtime(f)
def clear_cache():
global __mtime_cache
__mtime_cache = {}
def mark_dependency(d, f):
if f.startswith('./'):
f = "%s/%s" % (os.getcwd(), f[2:])
@@ -127,16 +123,15 @@ def init_parser(d):
def resolve_file(fn, d):
if not os.path.isabs(fn):
bbpath = d.getVar("BBPATH")
bbpath = d.getVar("BBPATH", True)
newfn, attempts = bb.utils.which(bbpath, fn, history=True)
for af in attempts:
mark_dependency(d, af)
if not newfn:
raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath))
fn = newfn
else:
mark_dependency(d, fn)
mark_dependency(d, fn)
if not os.path.isfile(fn):
raise IOError(errno.ENOENT, "file %s not found" % fn)

View File

@@ -30,6 +30,8 @@ import itertools
from bb import methodpool
from bb.parse import logger
_bbversions_re = re.compile(r"\[(?P<from>[0-9]+)-(?P<to>[0-9]+)\]")
class StatementGroup(list):
def eval(self, data):
for statement in self:
@@ -130,6 +132,7 @@ class DataNode(AstNode):
val = groupd["value"]
elif "colon" in groupd and groupd["colon"] != None:
e = data.createCopy()
bb.data.update_data(e)
op = "immediate"
val = e.expand(groupd["value"], key + "[:=]")
elif "append" in groupd and groupd["append"] != None:
@@ -335,12 +338,6 @@ def handleInherit(statements, filename, lineno, m):
classes = m.group(1)
statements.append(InheritNode(filename, lineno, classes))
def runAnonFuncs(d):
code = []
for funcname in d.getVar("__BBANONFUNCS", False) or []:
code.append("%s(d)" % funcname)
bb.utils.better_exec("\n".join(code), {"d": d})
def finalize(fn, d, variant = None):
saved_handlers = bb.event.get_handlers().copy()
@@ -350,15 +347,19 @@ 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", True) or "").split(), handlerfn, handlerln)
bb.event.fire(bb.event.RecipePreFinalise(fn), d)
bb.data.expandKeys(d)
runAnonFuncs(d)
bb.data.update_data(d)
code = []
for funcname in d.getVar("__BBANONFUNCS", False) or []:
code.append("%s(d)" % funcname)
bb.utils.better_exec("\n".join(code), {"d": d})
bb.data.update_data(d)
tasklist = d.getVar('__BBTASKS', False) or []
bb.event.fire(bb.event.RecipeTaskPreProcess(fn, list(tasklist)), d)
bb.build.add_tasks(tasklist, d)
bb.parse.siggen.finalise(fn, d, variant)
@@ -384,8 +385,29 @@ def _create_variants(datastores, names, function, onlyfinalise):
else:
create_variant("%s-%s" % (variant, name), datastores[variant], name)
def _expand_versions(versions):
def expand_one(version, start, end):
for i in range(start, end + 1):
ver = _bbversions_re.sub(str(i), version, 1)
yield ver
versions = iter(versions)
while True:
try:
version = next(versions)
except StopIteration:
break
range_ver = _bbversions_re.search(version)
if not range_ver:
yield version
else:
newversions = expand_one(version, int(range_ver.group("from")),
int(range_ver.group("to")))
versions = itertools.chain(newversions, versions)
def multi_finalize(fn, d):
appends = (d.getVar("__BBAPPEND") or "").split()
appends = (d.getVar("__BBAPPEND", True) or "").split()
for append in appends:
logger.debug(1, "Appending .bbappend file %s to %s", append, fn)
bb.parse.BBHandler.handle(append, d, True)
@@ -400,7 +422,51 @@ def multi_finalize(fn, d):
d.setVar("__SKIPPED", e.args[0])
datastores = {"": safe_d}
extended = d.getVar("BBCLASSEXTEND") or ""
versions = (d.getVar("BBVERSIONS", True) or "").split()
if versions:
pv = orig_pv = d.getVar("PV", True)
baseversions = {}
def verfunc(ver, d, pv_d = None):
if pv_d is None:
pv_d = d
overrides = d.getVar("OVERRIDES", True).split(":")
pv_d.setVar("PV", ver)
overrides.append(ver)
bpv = baseversions.get(ver) or orig_pv
pv_d.setVar("BPV", bpv)
overrides.append(bpv)
d.setVar("OVERRIDES", ":".join(overrides))
versions = list(_expand_versions(versions))
for pos, version in enumerate(list(versions)):
try:
pv, bpv = version.split(":", 2)
except ValueError:
pass
else:
versions[pos] = pv
baseversions[pv] = bpv
if pv in versions and not baseversions.get(pv):
versions.remove(pv)
else:
pv = versions.pop()
# This is necessary because our existing main datastore
# has already been finalized with the old PV, we need one
# that's been finalized with the new PV.
d = bb.data.createCopy(safe_d)
verfunc(pv, d, safe_d)
try:
finalize(fn, d)
except bb.parse.SkipRecipe as e:
d.setVar("__SKIPPED", e.args[0])
_create_variants(datastores, versions, verfunc, onlyfinalise)
extended = d.getVar("BBCLASSEXTEND", True) or ""
if extended:
# the following is to support bbextends with arguments, for e.g. multilib
# an example is as follows:
@@ -418,7 +484,7 @@ def multi_finalize(fn, d):
else:
extendedmap[ext] = ext
pn = d.getVar("PN")
pn = d.getVar("PN", True)
def extendfunc(name, d):
if name != extendedmap[name]:
d.setVar("BBEXTENDCURR", extendedmap[name])

View File

@@ -66,7 +66,7 @@ def inherit(files, fn, lineno, d):
file = os.path.join('classes', '%s.bbclass' % file)
if not os.path.isabs(file):
bbpath = d.getVar("BBPATH")
bbpath = d.getVar("BBPATH", True)
abs_fn, attempts = bb.utils.which(bbpath, file, history=True)
for af in attempts:
if af != abs_fn:
@@ -87,17 +87,17 @@ def get_statements(filename, absolute_filename, base_name):
try:
return cached_statements[absolute_filename]
except KeyError:
with open(absolute_filename, 'r') as f:
statements = ast.StatementGroup()
lineno = 0
while True:
lineno = lineno + 1
s = f.readline()
if not s: break
s = s.rstrip()
feeder(lineno, s, filename, base_name, statements)
file = open(absolute_filename, 'r')
statements = ast.StatementGroup()
lineno = 0
while True:
lineno = lineno + 1
s = file.readline()
if not s: break
s = s.rstrip()
feeder(lineno, s, filename, base_name, statements)
file.close()
if __inpython__:
# add a blank line to close out any python definition
feeder(lineno, "", filename, base_name, statements, eof=True)
@@ -131,6 +131,9 @@ def handle(fn, d, include):
abs_fn = resolve_file(fn, d)
if include:
bb.parse.mark_dependency(d, abs_fn)
# actual loading
statements = get_statements(fn, abs_fn, base_name)
@@ -141,7 +144,7 @@ def handle(fn, d, include):
try:
statements.eval(d)
except bb.parse.SkipRecipe:
d.setVar("__SKIPPED", True)
bb.data.setVar("__SKIPPED", True, d)
if include == 0:
return { "" : d }

View File

@@ -32,8 +32,8 @@ 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<exp>export\s*)?
(?P<var>[a-zA-Z0-9\-~_+.${}/]+?)
(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?
\s* (
@@ -56,9 +56,9 @@ __config_regexp__ = re.compile( r"""
""", re.X)
__include_regexp__ = re.compile( r"include\s+(.+)" )
__require_regexp__ = re.compile( r"require\s+(.+)" )
__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)$" )
__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/~]+)\[([a-zA-Z0-9\-_+.]+)\]$" )
__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/]+)$" )
__unset_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/]+)$" )
__unset_flag_regexp__ = re.compile( r"unset\s+([a-zA-Z0-9\-_+.${}/]+)\[([a-zA-Z0-9\-_+.${}/]+)\]$" )
def init(data):
topdir = data.getVar('TOPDIR', False)
@@ -69,38 +69,30 @@ def init(data):
def supports(fn, d):
return fn[-5:] == ".conf"
def include(parentfn, fns, lineno, data, error_out):
def include(parentfn, fn, lineno, data, error_out):
"""
error_out: A string indicating the verb (e.g. "include", "inherit") to be
used in a ParseError that will be raised if the file to be included could
not be included. Specify False to avoid raising an error in this case.
"""
fns = data.expand(fns)
parentfn = data.expand(parentfn)
# "include" or "require" accept zero to n space-separated file names to include.
for fn in fns.split():
include_single_file(parentfn, fn, lineno, data, error_out)
def include_single_file(parentfn, fn, lineno, data, error_out):
"""
Helper function for include() which does not expand or split its parameters.
"""
if parentfn == fn: # prevent infinite recursion
return None
fn = data.expand(fn)
parentfn = data.expand(parentfn)
if not os.path.isabs(fn):
dname = os.path.dirname(parentfn)
bbpath = "%s:%s" % (dname, data.getVar("BBPATH"))
bbpath = "%s:%s" % (dname, data.getVar("BBPATH", True))
abs_fn, attempts = bb.utils.which(bbpath, fn, history=True)
if abs_fn and bb.parse.check_dependency(data, abs_fn):
logger.warning("Duplicate inclusion for %s in %s" % (abs_fn, data.getVar('FILE')))
logger.warning("Duplicate inclusion for %s in %s" % (abs_fn, data.getVar('FILE', True)))
for af in attempts:
bb.parse.mark_dependency(data, af)
if abs_fn:
fn = abs_fn
elif bb.parse.check_dependency(data, fn):
logger.warning("Duplicate inclusion for %s in %s" % (fn, data.getVar('FILE')))
logger.warning("Duplicate inclusion for %s in %s" % (fn, data.getVar('FILE', True)))
try:
bb.parse.handle(fn, data, True)
@@ -134,6 +126,9 @@ def handle(fn, data, include):
abs_fn = resolve_file(fn, data)
f = open(abs_fn, 'r')
if include:
bb.parse.mark_dependency(data, abs_fn)
statements = ast.StatementGroup()
lineno = 0
while True:

View File

@@ -28,7 +28,11 @@ import sys
import warnings
from bb.compat import total_ordering
from collections import Mapping
import sqlite3
try:
import sqlite3
except ImportError:
from pysqlite2 import dbapi2 as sqlite3
sqlversion = sqlite3.sqlite_version_info
if sqlversion[0] < 3 or (sqlversion[0] == 3 and sqlversion[1] < 3):
@@ -203,8 +207,8 @@ def connect(database):
def persist(domain, d):
"""Convenience factory for SQLTable objects based upon metadata"""
import bb.utils
cachedir = (d.getVar("PERSISTENT_DIR") or
d.getVar("CACHE"))
cachedir = (d.getVar("PERSISTENT_DIR", True) or
d.getVar("CACHE", True))
if not cachedir:
logger.critical("Please set the 'PERSISTENT_DIR' or 'CACHE' variable")
sys.exit(1)

View File

@@ -94,53 +94,46 @@ def _logged_communicate(pipe, log, input, extrafiles):
if data is not None:
func(data)
def read_all_pipes(log, rin, outdata, errdata):
rlist = rin
stdoutbuf = b""
stderrbuf = b""
try:
r,w,e = select.select (rlist, [], [], 1)
except OSError as e:
if e.errno != errno.EINTR:
raise
readextras(r)
if pipe.stdout in r:
data = stdoutbuf + pipe.stdout.read()
if data is not None and len(data) > 0:
try:
data = data.decode("utf-8")
outdata.append(data)
log.write(data)
log.flush()
stdoutbuf = b""
except UnicodeDecodeError:
stdoutbuf = data
if pipe.stderr in r:
data = stderrbuf + pipe.stderr.read()
if data is not None and len(data) > 0:
try:
data = data.decode("utf-8")
errdata.append(data)
log.write(data)
log.flush()
stderrbuf = b""
except UnicodeDecodeError:
stderrbuf = data
try:
# Read all pipes while the process is open
while pipe.poll() is None:
read_all_pipes(log, rin, outdata, errdata)
rlist = rin
stdoutbuf = b""
stderrbuf = b""
try:
r,w,e = select.select (rlist, [], [], 1)
except OSError as e:
if e.errno != errno.EINTR:
raise
# Pocess closed, drain all pipes...
read_all_pipes(log, rin, outdata, errdata)
finally:
if pipe.stdout in r:
data = stdoutbuf + pipe.stdout.read()
if data is not None and len(data) > 0:
try:
data = data.decode("utf-8")
outdata.append(data)
log.write(data)
stdoutbuf = b""
except UnicodeDecodeError:
stdoutbuf = data
if pipe.stderr in r:
data = stderrbuf + pipe.stderr.read()
if data is not None and len(data) > 0:
try:
data = data.decode("utf-8")
errdata.append(data)
log.write(data)
stderrbuf = b""
except UnicodeDecodeError:
stderrbuf = data
readextras(r)
finally:
log.flush()
readextras([fobj for fobj, _ in extrafiles])
if pipe.stdout is not None:
pipe.stdout.close()
if pipe.stderr is not None:
@@ -169,9 +162,9 @@ def run(cmd, input=None, log=None, extrafiles=None, **options):
stdout, stderr = _logged_communicate(pipe, log, input, extrafiles)
else:
stdout, stderr = pipe.communicate(input)
if not stdout is None:
if stdout:
stdout = stdout.decode("utf-8")
if not stderr is None:
if stderr:
stderr = stderr.decode("utf-8")
if pipe.returncode != 0:

View File

@@ -48,6 +48,7 @@ def findProviders(cfgData, dataCache, pkg_pn = None):
# Need to ensure data store is expanded
localdata = data.createCopy(cfgData)
bb.data.update_data(localdata)
bb.data.expandKeys(localdata)
preferred_versions = {}
@@ -122,11 +123,11 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
# 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)
preferred_v = cfgData.getVar("PREFERRED_VERSION_pn-%s" % pn, True)
if not preferred_v:
preferred_v = cfgData.getVar("PREFERRED_VERSION_%s" % pn)
preferred_v = cfgData.getVar("PREFERRED_VERSION_%s" % pn, True)
if not preferred_v:
preferred_v = cfgData.getVar("PREFERRED_VERSION")
preferred_v = cfgData.getVar("PREFERRED_VERSION", True)
if preferred_v:
m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
@@ -244,17 +245,17 @@ 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(1, "providers for %s are: %s", item, list(pkg_pn.keys()))
# First add PREFERRED_VERSIONS
for pn in sorted(pkg_pn):
for pn in pkg_pn:
sortpkg_pn[pn] = sortPriorities(pn, dataCache, pkg_pn)
preferred_versions[pn] = findPreferredProvider(pn, cfgData, dataCache, sortpkg_pn[pn], item)
if preferred_versions[pn][1]:
eligible.append(preferred_versions[pn][1])
# Now add latest versions
for pn in sorted(sortpkg_pn):
for pn in sortpkg_pn:
if pn in preferred_versions and preferred_versions[pn][1]:
continue
preferred_versions[pn] = findLatestProvider(pn, cfgData, dataCache, sortpkg_pn[pn][0])
@@ -288,7 +289,7 @@ def filterProviders(providers, item, cfgData, dataCache):
eligible = _filterProviders(providers, item, cfgData, dataCache)
prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % item)
prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % item, True)
if prefervar:
dataCache.preferred[item] = prefervar
@@ -317,7 +318,7 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
eligible = _filterProviders(providers, item, cfgData, dataCache)
# First try and match any PREFERRED_RPROVIDER entry
prefervar = cfgData.getVar('PREFERRED_RPROVIDER_%s' % item)
prefervar = cfgData.getVar('PREFERRED_RPROVIDER_%s' % item, True)
foundUnique = False
if prefervar:
for p in eligible:
@@ -344,7 +345,7 @@ def filterProvidersRunTime(providers, item, cfgData, dataCache):
pn = dataCache.pkg_fn[p]
provides = dataCache.pn_provides[pn]
for provide in provides:
prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide)
prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
#logger.debug(1, "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)

View File

@@ -1,116 +0,0 @@
"""
BitBake 'remotedata' module
Provides support for using a datastore from the bitbake client
"""
# Copyright (C) 2016 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import bb.data
class RemoteDatastores:
"""Used on the server side to manage references to server-side datastores"""
def __init__(self, cooker):
self.cooker = cooker
self.datastores = {}
self.locked = []
self.nextindex = 1
def __len__(self):
return len(self.datastores)
def __getitem__(self, key):
if key is None:
return self.cooker.data
else:
return self.datastores[key]
def items(self):
return self.datastores.items()
def store(self, d, locked=False):
"""
Put a datastore into the collection. If locked=True then the datastore
is understood to be managed externally and cannot be released by calling
release().
"""
idx = self.nextindex
self.datastores[idx] = d
if locked:
self.locked.append(idx)
self.nextindex += 1
return idx
def check_store(self, d, locked=False):
"""
Put a datastore into the collection if it's not already in there;
in either case return the index
"""
for key, val in self.datastores.items():
if val is d:
idx = key
break
else:
idx = self.store(d, locked)
return idx
def release(self, idx):
"""Discard a datastore in the collection"""
if idx in self.locked:
raise Exception('Tried to release locked datastore %d' % idx)
del self.datastores[idx]
def receive_datastore(self, remote_data):
"""Receive a datastore object sent from the client (as prepared by transmit_datastore())"""
dct = dict(remote_data)
d = bb.data_smart.DataSmart()
d.dict = dct
while True:
if '_remote_data' in dct:
dsindex = dct['_remote_data']['_content']
del dct['_remote_data']
if dsindex is None:
dct['_data'] = self.cooker.data.dict
else:
dct['_data'] = self.datastores[dsindex].dict
break
elif '_data' in dct:
idct = dict(dct['_data'])
dct['_data'] = idct
dct = idct
else:
break
return d
@staticmethod
def transmit_datastore(d):
"""Prepare a datastore object for sending over IPC from the client end"""
# FIXME content might be a dict, need to turn that into a list as well
def copy_dicts(dct):
if '_remote_data' in dct:
dsindex = dct['_remote_data']['_content'].dsindex
newdct = dct.copy()
newdct['_remote_data'] = {'_content': dsindex}
return list(newdct.items())
elif '_data' in dct:
newdct = dct.copy()
newdata = copy_dicts(dct['_data'])
if newdata:
newdct['_data'] = newdata
return list(newdct.items())
return None
main_dict = copy_dicts(d.dict)
return main_dict

View File

@@ -36,7 +36,6 @@ from bb import msg, data, event
from bb import monitordisk
import subprocess
import pickle
from multiprocessing import Process
bblogger = logging.getLogger("BitBake")
logger = logging.getLogger("BitBake.RunQueue")
@@ -181,21 +180,9 @@ class RunQueueScheduler(object):
if self.rq.stats.active < self.rq.number_tasks:
return self.next_buildable_task()
def newbuildable(self, task):
def newbuilable(self, task):
self.buildable.append(task)
def describe_task(self, taskid):
result = 'ID %s' % taskid
if self.rev_prio_map:
result = result + (' pri %d' % self.rev_prio_map[taskid])
return result
def dump_prio(self, comment):
bb.debug(3, '%s (most important first):\n%s' %
(comment,
'\n'.join(['%d. %s' % (index + 1, self.describe_task(taskid)) for
index, taskid in enumerate(self.prio_map)])))
class RunQueueSchedulerSpeed(RunQueueScheduler):
"""
A scheduler optimised for speed. The priority map is sorted by task weight,
@@ -225,100 +212,35 @@ class RunQueueSchedulerSpeed(RunQueueScheduler):
class RunQueueSchedulerCompletion(RunQueueSchedulerSpeed):
"""
A scheduler optimised to complete .bb files as quickly as possible. The
A scheduler optimised to complete .bb files are quickly as possible. The
priority map is sorted by task weight, but then reordered so once a given
.bb file starts to build, it's completed as quickly as possible by
running all tasks related to the same .bb file one after the after.
This works well where disk space is at a premium and classes like OE's
rm_work are in force.
.bb file starts to build, it's completed as quickly as possible. This works
well where disk space is at a premium and classes like OE's rm_work are in
force.
"""
name = "completion"
def __init__(self, runqueue, rqdata):
super(RunQueueSchedulerCompletion, self).__init__(runqueue, rqdata)
RunQueueSchedulerSpeed.__init__(self, runqueue, rqdata)
# Extract list of tasks for each recipe, with tasks sorted
# ascending from "must run first" (typically do_fetch) to
# "runs last" (do_build). The speed scheduler prioritizes
# tasks that must run first before the ones that run later;
# this is what we depend on here.
task_lists = {}
for taskid in self.prio_map:
fn, taskname = taskid.rsplit(':', 1)
task_lists.setdefault(fn, []).append(taskname)
#FIXME - whilst this groups all fns together it does not reorder the
#fn groups optimally.
# Now unify the different task lists. The strategy is that
# common tasks get skipped and new ones get inserted after the
# preceeding common one(s) as they are found. Because task
# lists should differ only by their number of tasks, but not
# the ordering of the common tasks, this should result in a
# deterministic result that is a superset of the individual
# task ordering.
all_tasks = []
for recipe, new_tasks in task_lists.items():
index = 0
old_task = all_tasks[index] if index < len(all_tasks) else None
for new_task in new_tasks:
if old_task == new_task:
# Common task, skip it. This is the fast-path which
# avoids a full search.
index += 1
old_task = all_tasks[index] if index < len(all_tasks) else None
else:
try:
index = all_tasks.index(new_task)
# Already present, just not at the current
# place. We re-synchronized by changing the
# index so that it matches again. Now
# move on to the next existing task.
index += 1
old_task = all_tasks[index] if index < len(all_tasks) else None
except ValueError:
# Not present. Insert before old_task, which
# remains the same (but gets shifted back).
all_tasks.insert(index, new_task)
index += 1
bb.debug(3, 'merged task list: %s' % all_tasks)
# Now reverse the order so that tasks that finish the work on one
# recipe are considered more imporant (= come first). The ordering
# is now so that do_build is most important.
all_tasks.reverse()
# Group tasks of the same kind before tasks of less important
# kinds at the head of the queue (because earlier = lower
# priority number = runs earlier), while preserving the
# ordering by recipe. If recipe foo is more important than
# bar, then the goal is to work on foo's do_populate_sysroot
# before bar's do_populate_sysroot and on the more important
# tasks of foo before any of the less important tasks in any
# other recipe (if those other recipes are more important than
# foo).
#
# All of this only applies when tasks are runable. Explicit
# dependencies still override this ordering by priority.
#
# Here's an example why this priority re-ordering helps with
# minimizing disk usage. Consider a recipe foo with a higher
# priority than bar where foo DEPENDS on bar. Then the
# implicit rule (from base.bbclass) is that foo's do_configure
# depends on bar's do_populate_sysroot. This ensures that
# bar's do_populate_sysroot gets done first. Normally the
# tasks from foo would continue to run once that is done, and
# bar only gets completed and cleaned up later. By ordering
# bar's task that depend on bar's do_populate_sysroot before foo's
# do_configure, that problem gets avoided.
task_index = 0
self.dump_prio('original priorities')
for task in all_tasks:
for index in range(task_index, self.numTasks):
taskid = self.prio_map[index]
taskname = taskid.rsplit(':', 1)[1]
if taskname == task:
del self.prio_map[index]
self.prio_map.insert(task_index, taskid)
task_index += 1
self.dump_prio('completion priorities')
basemap = copy.deepcopy(self.prio_map)
self.prio_map = []
while (len(basemap) > 0):
entry = basemap.pop(0)
self.prio_map.append(entry)
fn = fn_from_tid(entry)
todel = []
for entry in basemap:
entry_fn = fn_from_tid(entry)
if entry_fn == fn:
todel.append(basemap.index(entry))
self.prio_map.append(entry)
todel.reverse()
for idx in todel:
del basemap[idx]
class RunTaskEntry(object):
def __init__(self):
@@ -340,11 +262,10 @@ class RunQueueData:
self.rq = rq
self.warn_multi_bb = False
self.stampwhitelist = cfgData.getVar("BB_STAMP_WHITELIST") or ""
self.multi_provider_whitelist = (cfgData.getVar("MULTI_PROVIDER_WHITELIST") or "").split()
self.stampwhitelist = cfgData.getVar("BB_STAMP_WHITELIST", True) or ""
self.multi_provider_whitelist = (cfgData.getVar("MULTI_PROVIDER_WHITELIST", True) or "").split()
self.setscenewhitelist = get_setscene_enforce_whitelist(cfgData)
self.setscenewhitelist_checked = False
self.setscene_enforce = (cfgData.getVar('BB_SETSCENE_ENFORCE') == "1")
self.init_progress_reporter = bb.progress.DummyMultiStageProcessProgressReporter()
self.reset()
@@ -581,6 +502,12 @@ class RunQueueData:
if t in taskData[mc].taskentries:
depends.add(t)
def add_resolved_dependencies(mc, fn, tasknames, depends):
for taskname in tasknames:
tid = build_tid(mc, fn, taskname)
if tid in self.runtaskentries:
depends.add(tid)
for mc in taskData:
for tid in taskData[mc].taskentries:
@@ -638,8 +565,6 @@ class RunQueueData:
for (depname, idependtask) in irdepends:
if depname in taskData[mc].run_targets:
# Won't be in run_targets if ASSUME_PROVIDED
if not taskData[mc].run_targets[depname]:
continue
depdata = taskData[mc].run_targets[depname][0]
if depdata is not None:
t = depdata + ":" + idependtask
@@ -667,106 +592,54 @@ class RunQueueData:
recursiveitasks[tid].append(newdep)
self.runtaskentries[tid].depends = depends
# Remove all self references
self.runtaskentries[tid].depends.discard(tid)
#self.dump_data()
self.init_progress_reporter.next_stage()
# Resolve recursive 'recrdeptask' dependencies (Part B)
#
# e.g. do_sometask[recrdeptask] = "do_someothertask"
# (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
# We need to do this separately since we need all of runtaskentries[*].depends to be complete before this is processed
self.init_progress_reporter.next_stage(len(recursivetasks))
extradeps = {}
for taskcounter, tid in enumerate(recursivetasks):
extradeps[tid] = set(self.runtaskentries[tid].depends)
# Generating/interating recursive lists of dependencies is painful and potentially slow
# Precompute recursive task dependencies here by:
# a) create a temp list of reverse dependencies (revdeps)
# b) walk up the ends of the chains (when a given task no longer has dependencies i.e. len(deps) == 0)
# c) combine the total list of dependencies in cumulativedeps
# d) optimise by pre-truncating 'task' off the items in cumulativedeps (keeps items in sets lower)
tasknames = recursivetasks[tid]
seendeps = set()
def generate_recdeps(t):
newdeps = set()
(mc, fn, taskname, _) = split_tid_mcfn(t)
add_resolved_dependencies(mc, fn, tasknames, newdeps)
extradeps[tid].update(newdeps)
seendeps.add(t)
newdeps.add(t)
for i in newdeps:
task = self.runtaskentries[i].task
for n in self.runtaskentries[i].depends:
if n not in seendeps:
generate_recdeps(n)
generate_recdeps(tid)
if tid in recursiveitasks:
for dep in recursiveitasks[tid]:
generate_recdeps(dep)
self.init_progress_reporter.update(taskcounter)
# Remove circular references so that do_a[recrdeptask] = "do_a do_b" can work
for tid in recursivetasks:
extradeps[tid].difference_update(recursivetasksselfref)
revdeps = {}
deps = {}
cumulativedeps = {}
for tid in self.runtaskentries:
deps[tid] = set(self.runtaskentries[tid].depends)
revdeps[tid] = set()
cumulativedeps[tid] = set()
# Generate a temp list of reverse dependencies
for tid in self.runtaskentries:
for dep in self.runtaskentries[tid].depends:
revdeps[dep].add(tid)
# Find the dependency chain endpoints
endpoints = set()
for tid in self.runtaskentries:
if len(deps[tid]) == 0:
endpoints.add(tid)
# Iterate the chains collating dependencies
while endpoints:
next = set()
for tid in endpoints:
for dep in revdeps[tid]:
cumulativedeps[dep].add(fn_from_tid(tid))
cumulativedeps[dep].update(cumulativedeps[tid])
if tid in deps[dep]:
deps[dep].remove(tid)
if len(deps[dep]) == 0:
next.add(dep)
endpoints = next
#for tid in deps:
# if len(deps[tid]) != 0:
# bb.warn("Sanity test failure, dependencies left for %s (%s)" % (tid, deps[tid]))
# Loop here since recrdeptasks can depend upon other recrdeptasks and we have to
# resolve these recursively until we aren't adding any further extra dependencies
extradeps = True
while extradeps:
extradeps = 0
for tid in recursivetasks:
tasknames = recursivetasks[tid]
totaldeps = set(self.runtaskentries[tid].depends)
if tid in recursiveitasks:
totaldeps.update(recursiveitasks[tid])
for dep in recursiveitasks[tid]:
if dep not in self.runtaskentries:
continue
totaldeps.update(self.runtaskentries[dep].depends)
deps = set()
for dep in totaldeps:
if dep in cumulativedeps:
deps.update(cumulativedeps[dep])
for t in deps:
for taskname in tasknames:
newtid = t + ":" + taskname
if newtid == tid:
continue
if newtid in self.runtaskentries and newtid not in self.runtaskentries[tid].depends:
extradeps += 1
self.runtaskentries[tid].depends.add(newtid)
# Handle recursive tasks which depend upon other recursive tasks
deps = set()
for dep in self.runtaskentries[tid].depends.intersection(recursivetasks):
deps.update(self.runtaskentries[dep].depends.difference(self.runtaskentries[tid].depends))
for newtid in deps:
for taskname in tasknames:
if not newtid.endswith(":" + taskname):
continue
if newtid in self.runtaskentries:
extradeps += 1
self.runtaskentries[tid].depends.add(newtid)
bb.debug(1, "Added %s recursive dependencies in this loop" % extradeps)
# Remove recrdeptask circular references so that do_a[recrdeptask] = "do_a do_b" can work
for tid in recursivetasksselfref:
self.runtaskentries[tid].depends.difference_update(recursivetasksselfref)
task = self.runtaskentries[tid].task
# Add in extra dependencies
if tid in extradeps:
self.runtaskentries[tid].depends = extradeps[tid]
# Remove all self references
if tid in self.runtaskentries[tid].depends:
logger.debug(2, "Task %s contains self reference!", tid)
self.runtaskentries[tid].depends.remove(tid)
self.init_progress_reporter.next_stage()
@@ -841,58 +714,14 @@ class RunQueueData:
#
# Once all active tasks are marked, prune the ones we don't need.
delcount = {}
delcount = 0
for tid in list(self.runtaskentries.keys()):
if tid not in runq_build:
delcount[tid] = self.runtaskentries[tid]
del self.runtaskentries[tid]
# Handle --runall
if self.cooker.configuration.runall:
# re-run the mark_active and then drop unused tasks from new list
runq_build = {}
for task in self.cooker.configuration.runall:
runall_tids = set()
for tid in list(self.runtaskentries):
wanttid = fn_from_tid(tid) + ":do_%s" % task
if wanttid in delcount:
self.runtaskentries[wanttid] = delcount[wanttid]
if wanttid in self.runtaskentries:
runall_tids.add(wanttid)
for tid in list(runall_tids):
mark_active(tid,1)
for tid in list(self.runtaskentries.keys()):
if tid not in runq_build:
delcount[tid] = self.runtaskentries[tid]
del self.runtaskentries[tid]
if len(self.runtaskentries) == 0:
bb.msg.fatal("RunQueue", "Could not find any tasks with the tasknames %s to run within the recipes of the taskgraphs of the targets %s" % (str(self.cooker.configuration.runall), str(self.targets)))
delcount += 1
self.init_progress_reporter.next_stage()
# Handle runonly
if self.cooker.configuration.runonly:
# re-run the mark_active and then drop unused tasks from new list
runq_build = {}
for task in self.cooker.configuration.runonly:
runonly_tids = { k: v for k, v in self.runtaskentries.items() if taskname_from_tid(k) == "do_%s" % task }
for tid in list(runonly_tids):
mark_active(tid,1)
for tid in list(self.runtaskentries.keys()):
if tid not in runq_build:
delcount[tid] = self.runtaskentries[tid]
del self.runtaskentries[tid]
if len(self.runtaskentries) == 0:
bb.msg.fatal("RunQueue", "Could not find any tasks with the tasknames %s to run within the taskgraphs of the targets %s" % (str(self.cooker.configuration.runonly), str(self.targets)))
#
# Step D - Sanity checks and computation
#
@@ -904,7 +733,7 @@ class RunQueueData:
else:
bb.msg.fatal("RunQueue", "No active tasks and not in --continue mode?! Please report this bug.")
logger.verbose("Pruned %s inactive tasks, %s left", len(delcount), len(self.runtaskentries))
logger.verbose("Pruned %s inactive tasks, %s left", delcount, len(self.runtaskentries))
logger.verbose("Assign Weightings")
@@ -1147,22 +976,16 @@ class RunQueue:
self.cfgData = cfgData
self.rqdata = RunQueueData(self, cooker, cfgData, dataCaches, taskData, targets)
self.stamppolicy = cfgData.getVar("BB_STAMP_POLICY") or "perfile"
self.hashvalidate = cfgData.getVar("BB_HASHCHECK_FUNCTION") or None
self.setsceneverify = cfgData.getVar("BB_SETSCENE_VERIFY_FUNCTION2") or None
self.depvalidate = cfgData.getVar("BB_SETSCENE_DEPVALID") or None
self.stamppolicy = cfgData.getVar("BB_STAMP_POLICY", True) or "perfile"
self.hashvalidate = cfgData.getVar("BB_HASHCHECK_FUNCTION", True) or None
self.setsceneverify = cfgData.getVar("BB_SETSCENE_VERIFY_FUNCTION2", True) or None
self.depvalidate = cfgData.getVar("BB_SETSCENE_DEPVALID", True) or None
self.state = runQueuePrepare
# For disk space monitor
# Invoked at regular time intervals via the bitbake heartbeat event
# while the build is running. We generate a unique name for the handler
# here, just in case that there ever is more than one RunQueue instance,
# start the handler when reaching runQueueSceneRun, and stop it when
# done with the build.
self.dm = monitordisk.diskMonitor(cfgData)
self.dm_event_handler_name = '_bb_diskmonitor_' + str(id(self))
self.dm_event_handler_registered = False
self.rqexe = None
self.worker = {}
self.fakeworker = {}
@@ -1175,8 +998,8 @@ class RunQueue:
if fakeroot:
magic = magic + "beef"
mcdata = self.cooker.databuilder.mcdata[mc]
fakerootcmd = mcdata.getVar("FAKEROOTCMD")
fakerootenv = (mcdata.getVar("FAKEROOTBASEENV") or "").split()
fakerootcmd = mcdata.getVar("FAKEROOTCMD", True)
fakerootenv = (mcdata.getVar("FAKEROOTBASEENV", True) or "").split()
env = os.environ.copy()
for key, value in (var.split('=') for var in fakerootenv):
env[key] = value
@@ -1202,13 +1025,12 @@ class RunQueue:
"logdefaultverboselogs" : bb.msg.loggerVerboseLogs,
"logdefaultdomain" : bb.msg.loggerDefaultDomains,
"prhost" : self.cooker.prhost,
"buildname" : self.cfgData.getVar("BUILDNAME"),
"date" : self.cfgData.getVar("DATE"),
"time" : self.cfgData.getVar("TIME"),
"buildname" : self.cfgData.getVar("BUILDNAME", True),
"date" : self.cfgData.getVar("DATE", True),
"time" : self.cfgData.getVar("TIME", True),
}
worker.stdin.write(b"<cookerconfig>" + pickle.dumps(self.cooker.configuration) + b"</cookerconfig>")
worker.stdin.write(b"<extraconfigdata>" + pickle.dumps(self.cooker.extraconfigdata) + b"</extraconfigdata>")
worker.stdin.write(b"<workerdata>" + pickle.dumps(workerdata) + b"</workerdata>")
worker.stdin.flush()
@@ -1386,12 +1208,10 @@ class RunQueue:
self.rqdata.init_progress_reporter.next_stage()
self.rqexe = RunQueueExecuteScenequeue(self)
if self.state in [runQueueSceneRun, runQueueRunning, runQueueCleanUp]:
self.dm.check(self)
if self.state is runQueueSceneRun:
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 [runQueueSceneRun, runQueueRunning, runQueueCleanUp] else False,
('bb.event.HeartbeatEvent',))
self.dm_event_handler_registered = True
retval = self.rqexe.execute()
if self.state is runQueueRunInit:
@@ -1410,13 +1230,7 @@ class RunQueue:
if self.state is runQueueCleanUp:
retval = self.rqexe.finish()
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)
self.dm_event_handler_registered = False
if build_done and self.rqexe:
if (self.state is runQueueComplete or self.state is runQueueFailed) and self.rqexe:
self.teardown_workers()
if self.rqexe.stats.failed:
logger.info("Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and %d failed.", self.rqexe.stats.completed + self.rqexe.stats.failed, self.rqexe.stats.skipped, self.rqexe.stats.failed)
@@ -1425,7 +1239,12 @@ class RunQueue:
logger.info("Tasks Summary: Attempted %d tasks of which %d didn't need to be rerun and all succeeded.", self.rqexe.stats.completed, self.rqexe.stats.skipped)
if self.state is runQueueFailed:
raise bb.runqueue.TaskFailure(self.rqexe.failed_tids)
if not self.rqdata.taskData[''].tryaltconfigs:
raise bb.runqueue.TaskFailure(self.rqexe.failed_tids)
for tid in self.rqexe.failed_tids:
(mc, fn, tn, _) = split_tid_mcfn(tid)
self.rqdata.taskData[mc].fail_fn(fn)
self.rqdata.reset()
if self.state is runQueueComplete:
# All done
@@ -1468,36 +1287,15 @@ class RunQueue:
else:
self.rqexe.finish()
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))
siggen = bb.parse.siggen
dataCaches = self.rqdata.dataCaches
siggen.dump_sigfn(fn, dataCaches, options)
def dump_signatures(self, options):
fns = set()
done = set()
bb.note("Reparsing files to collect dependency data")
bb_cache = bb.cache.NoCache(self.cooker.databuilder)
for tid in self.rqdata.runtaskentries:
fn = fn_from_tid(tid)
fns.add(fn)
max_process = int(self.cfgData.getVar("BB_NUMBER_PARSE_THREADS") or os.cpu_count() or 1)
# We cannot use the real multiprocessing.Pool easily due to some local data
# that can't be pickled. This is a cheap multi-process solution.
launched = []
while fns:
if len(launched) < max_process:
p = Process(target=self.rq_dump_sigfn, args=(fns.pop(), options))
p.start()
launched.append(p)
for q in launched:
# The finished processes are joined when calling is_alive()
if not q.is_alive():
launched.remove(q)
for p in launched:
p.join()
if fn not in done:
the_data = bb_cache.loadDataFull(fn, self.cooker.collection.get_file_appends(fn))
done.add(fn)
bb.parse.siggen.dump_sigs(self.rqdata.dataCaches, options)
@@ -1528,7 +1326,7 @@ class RunQueue:
sq_hash.append(self.rqdata.runtaskentries[tid].hash)
sq_taskname.append(taskname)
sq_task.append(tid)
locs = { "sq_fn" : sq_fn, "sq_task" : sq_taskname, "sq_hash" : sq_hash, "sq_hashfn" : sq_hashfn, "d" : self.cooker.data }
locs = { "sq_fn" : sq_fn, "sq_task" : sq_taskname, "sq_hash" : sq_hash, "sq_hashfn" : sq_hashfn, "d" : self.cooker.expanded_data }
try:
call = self.hashvalidate + "(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=True)"
valid = bb.utils.better_eval(call, locs)
@@ -1629,8 +1427,8 @@ class RunQueueExecute:
self.cfgData = rq.cfgData
self.rqdata = rq.rqdata
self.number_tasks = int(self.cfgData.getVar("BB_NUMBER_THREADS") or 1)
self.scheduler = self.cfgData.getVar("BB_SCHEDULER") or "speed"
self.number_tasks = int(self.cfgData.getVar("BB_NUMBER_THREADS", True) or 1)
self.scheduler = self.cfgData.getVar("BB_SCHEDULER", True) or "speed"
self.runq_buildable = set()
self.runq_running = set()
@@ -1712,7 +1510,7 @@ class RunQueueExecute:
pn = self.rqdata.dataCaches[mc].pkg_fn[taskfn]
taskdata[dep] = [pn, taskname, fn]
call = self.rq.depvalidate + "(task, taskdata, notneeded, d)"
locs = { "task" : task, "taskdata" : taskdata, "notneeded" : self.scenequeue_notneeded, "d" : self.cooker.data }
locs = { "task" : task, "taskdata" : taskdata, "notneeded" : self.scenequeue_notneeded, "d" : self.cooker.expanded_data }
valid = bb.utils.better_eval(call, locs)
return valid
@@ -1780,7 +1578,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
invalidtasks.append(tid)
call = self.rq.setsceneverify + "(covered, tasknames, fns, d, invalidtasks=invalidtasks)"
locs = { "covered" : self.rq.scenequeue_covered, "tasknames" : tasknames, "fns" : fns, "d" : self.cooker.data, "invalidtasks" : invalidtasks }
locs = { "covered" : self.rq.scenequeue_covered, "tasknames" : tasknames, "fns" : fns, "d" : self.cooker.expanded_data, "invalidtasks" : invalidtasks }
covered_remove = bb.utils.better_eval(call, locs)
def removecoveredtask(tid):
@@ -1832,7 +1630,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
if type(obj) is type and
issubclass(obj, RunQueueScheduler))
user_schedulers = self.cfgData.getVar("BB_SCHEDULERS")
user_schedulers = self.cfgData.getVar("BB_SCHEDULERS", True)
if user_schedulers:
for sched in user_schedulers.split():
if not "." in sched:
@@ -1851,7 +1649,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
def setbuildable(self, task):
self.runq_buildable.add(task)
self.sched.newbuildable(task)
self.sched.newbuilable(task)
def task_completeoutright(self, task):
"""
@@ -1904,7 +1702,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
Run the tasks in a queue prepared by rqdata.prepare()
"""
if self.rqdata.setscenewhitelist is not None and not self.rqdata.setscenewhitelist_checked:
if self.rqdata.setscenewhitelist and not self.rqdata.setscenewhitelist_checked:
self.rqdata.setscenewhitelist_checked = True
# Check tasks that are going to run against the whitelist
@@ -1977,7 +1775,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
bb.event.fire(startevent, self.cfgData)
self.runq_running.add(task)
self.stats.taskActive()
if not (self.cooker.configuration.dry_run or self.rqdata.setscene_enforce):
if not self.cooker.configuration.dry_run:
bb.build.make_stamp(taskname, self.rqdata.dataCaches[mc], taskfn)
self.task_complete(task)
return True
@@ -1988,7 +1786,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
taskdepdata = self.build_taskdepdata(task)
taskdep = self.rqdata.dataCaches[mc].task_deps[taskfn]
if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not (self.cooker.configuration.dry_run or self.rqdata.setscene_enforce):
if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not self.cooker.configuration.dry_run:
if not mc in self.rq.fakeworker:
try:
self.rq.start_fakeworker(self, mc)
@@ -1997,10 +1795,10 @@ class RunQueueExecuteTasks(RunQueueExecute):
self.rq.state = runQueueFailed
self.stats.taskFailed()
return True
self.rq.fakeworker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, 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, False, self.cooker.collection.get_file_appends(fn), taskdepdata)) + b"</runtask>")
self.rq.fakeworker[mc].process.stdin.flush()
else:
self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, 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, False, self.cooker.collection.get_file_appends(taskfn), taskdepdata)) + b"</runtask>")
self.rq.worker[mc].process.stdin.flush()
self.build_stamps[task] = bb.build.stampfile(taskname, self.rqdata.dataCaches[mc], taskfn, noextra=True)
@@ -2041,8 +1839,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
pn = self.rqdata.dataCaches[mc].pkg_fn[taskfn]
deps = self.rqdata.runtaskentries[revdep].depends
provides = self.rqdata.dataCaches[mc].fn_provides[taskfn]
taskhash = self.rqdata.runtaskentries[revdep].hash
taskdepdata[revdep] = [pn, taskname, fn, deps, provides, taskhash]
taskdepdata[revdep] = [pn, taskname, fn, deps, provides]
for revdep2 in deps:
if revdep2 not in taskdepdata:
additional.append(revdep2)
@@ -2095,8 +1892,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
for tid in self.rqdata.runq_setscene_tids:
#bb.warn("Added endpoint 2 %s" % (tid))
for dep in self.rqdata.runtaskentries[tid].depends:
if tid in sq_revdeps[dep]:
sq_revdeps[dep].remove(tid)
if dep not in endpoints:
endpoints[dep] = set()
#bb.warn(" Added endpoint 3 %s" % (dep))
@@ -2116,13 +1911,12 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
if point in self.rqdata.runq_setscene_tids:
sq_revdeps_new[point] = tasks
tasks = set()
continue
for dep in self.rqdata.runtaskentries[point].depends:
if point in sq_revdeps[dep]:
sq_revdeps[dep].remove(point)
if tasks:
sq_revdeps_new[dep] |= tasks
if len(sq_revdeps[dep]) == 0 and dep not in self.rqdata.runq_setscene_tids:
if (len(sq_revdeps[dep]) == 0 or len(sq_revdeps_new[dep]) != 0) and dep not in self.rqdata.runq_setscene_tids:
newendpoints[dep] = task
if len(newendpoints) != 0:
process_endpoints(newendpoints)
@@ -2278,7 +2072,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
sq_taskname.append(taskname)
sq_task.append(tid)
call = self.rq.hashvalidate + "(sq_fn, sq_task, sq_hash, sq_hashfn, d)"
locs = { "sq_fn" : sq_fn, "sq_task" : sq_taskname, "sq_hash" : sq_hash, "sq_hashfn" : sq_hashfn, "d" : self.cooker.data }
locs = { "sq_fn" : sq_fn, "sq_task" : sq_taskname, "sq_hash" : sq_hash, "sq_hashfn" : sq_hashfn, "d" : self.cooker.expanded_data }
valid = bb.utils.better_eval(call, locs)
valid_new = stamppresent
@@ -2319,7 +2113,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
self.scenequeue_updatecounters(task)
def check_taskfail(self, task):
if self.rqdata.setscenewhitelist is not None:
if self.rqdata.setscenewhitelist:
realtask = task.split('_setscene')[0]
(mc, fn, taskname, taskfn) = split_tid_mcfn(realtask)
pn = self.rqdata.dataCaches[mc].pkg_fn[taskfn]
@@ -2405,16 +2199,14 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
startevent = sceneQueueTaskStarted(task, self.stats, self.rq)
bb.event.fire(startevent, self.cfgData)
taskdepdata = self.build_taskdepdata(task)
taskdep = self.rqdata.dataCaches[mc].task_deps[taskfn]
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, 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, True, self.cooker.collection.get_file_appends(taskfn), None)) + b"</runtask>")
self.rq.fakeworker[mc].process.stdin.flush()
else:
self.rq.worker[mc].process.stdin.write(b"<runtask>" + pickle.dumps((taskfn, task, taskname, 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, True, self.cooker.collection.get_file_appends(taskfn), None)) + b"</runtask>")
self.rq.worker[mc].process.stdin.flush()
self.build_stamps[task] = bb.build.stampfile(taskname, self.rqdata.dataCaches[mc], taskfn, noextra=True)
@@ -2437,7 +2229,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
self.rq.scenequeue_covered = self.scenequeue_covered
self.rq.scenequeue_notcovered = self.scenequeue_notcovered
logger.debug(1, 'We can skip tasks %s', "\n".join(sorted(self.rq.scenequeue_covered)))
logger.debug(1, 'We can skip tasks %s', sorted(self.rq.scenequeue_covered))
self.rq.state = runQueueRunInit
@@ -2449,44 +2241,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
def runqueue_process_waitpid(self, task, status):
RunQueueExecute.runqueue_process_waitpid(self, task, status)
def build_taskdepdata(self, task):
def getsetscenedeps(tid):
deps = set()
(mc, fn, taskname, _) = split_tid_mcfn(tid)
realtid = tid + "_setscene"
idepends = self.rqdata.taskData[mc].taskentries[realtid].idepends
for (depname, idependtask) in idepends:
if depname not in self.rqdata.taskData[mc].build_targets:
continue
depfn = self.rqdata.taskData[mc].build_targets[depname][0]
if depfn is None:
continue
deptid = depfn + ":" + idependtask.replace("_setscene", "")
deps.add(deptid)
return deps
taskdepdata = {}
next = getsetscenedeps(task)
next.add(task)
while next:
additional = []
for revdep in next:
(mc, fn, taskname, taskfn) = split_tid_mcfn(revdep)
pn = self.rqdata.dataCaches[mc].pkg_fn[taskfn]
deps = getsetscenedeps(revdep)
provides = self.rqdata.dataCaches[mc].fn_provides[taskfn]
taskhash = self.rqdata.runtaskentries[revdep].hash
taskdepdata[revdep] = [pn, taskname, fn, deps, provides, taskhash]
for revdep2 in deps:
if revdep2 not in taskdepdata:
additional.append(revdep2)
next = additional
#bb.note("Task %s: " % task + str(taskdepdata).replace("], ", "],\n"))
return taskdepdata
class TaskFailure(Exception):
"""
Exception raised when a task in a runqueue fails
@@ -2553,9 +2307,6 @@ class runQueueTaskFailed(runQueueEvent):
runQueueEvent.__init__(self, task, stats, rq)
self.exitcode = exitcode
def __str__(self):
return "Task (%s) failed with exit code '%s'" % (self.taskstring, self.exitcode)
class sceneQueueTaskFailed(sceneQueueEvent):
"""
Event notifying a setscene task failed
@@ -2564,9 +2315,6 @@ class sceneQueueTaskFailed(sceneQueueEvent):
sceneQueueEvent.__init__(self, task, stats, rq)
self.exitcode = exitcode
def __str__(self):
return "Setscene task (%s) failed with exit code '%s' - real task will be run instead" % (self.taskstring, self.exitcode)
class sceneQueueComplete(sceneQueueEvent):
"""
Event when all the sceneQueue tasks are complete
@@ -2658,9 +2406,9 @@ class runQueuePipe():
self.input.close()
def get_setscene_enforce_whitelist(d):
if d.getVar('BB_SETSCENE_ENFORCE') != '1':
if d.getVar('BB_SETSCENE_ENFORCE', True) != '1':
return None
whitelist = (d.getVar("BB_SETSCENE_ENFORCE_WHITELIST") or "").split()
whitelist = (d.getVar("BB_SETSCENE_ENFORCE_WHITELIST", True) or "").split()
outlist = []
for item in whitelist[:]:
if item.startswith('%:'):
@@ -2673,7 +2421,7 @@ def get_setscene_enforce_whitelist(d):
def check_setscene_enforce_whitelist(pn, taskname, whitelist):
import fnmatch
if whitelist is not None:
if whitelist:
item = '%s:%s' % (pn, taskname)
for whitelist_item in whitelist:
if fnmatch.fnmatch(item, whitelist_item):

View File

@@ -18,4 +18,82 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
""" Base code for Bitbake server process
Have a common base for that all Bitbake server classes ensures a consistent
approach to the interface, and minimize risks associated with code duplication.
"""
""" BaseImplServer() the base class for all XXServer() implementations.
These classes contain the actual code that runs the server side, i.e.
listens for the commands and executes them. Although these implementations
contain all the data of the original bitbake command, i.e the cooker instance,
they may well run on a different process or even machine.
"""
class BaseImplServer():
def __init__(self):
self._idlefuns = {}
def addcooker(self, cooker):
self.cooker = cooker
def register_idle_function(self, function, data):
"""Register a function to be called while the server is idle"""
assert hasattr(function, '__call__')
self._idlefuns[function] = data
""" BitBakeBaseServerConnection class is the common ancestor to all
BitBakeServerConnection classes.
These classes control the remote server. The only command currently
implemented is the terminate() command.
"""
class BitBakeBaseServerConnection():
def __init__(self, serverImpl):
pass
def terminate(self):
pass
def setupEventQueue(self):
pass
""" BitBakeBaseServer class is the common ancestor to all Bitbake servers
Derive this class in order to implement a BitBakeServer which is the
controlling stub for the actual server implementation
"""
class BitBakeBaseServer(object):
def initServer(self):
self.serverImpl = None # we ensure a runtime crash if not overloaded
self.connection = None
return
def addcooker(self, cooker):
self.cooker = cooker
self.serverImpl.addcooker(cooker)
def getServerIdleCB(self):
return self.serverImpl.register_idle_function
def saveConnectionDetails(self):
return
def detach(self):
return
def establishConnection(self, featureset):
raise "Must redefine the %s.establishConnection()" % self.__class__.__name__
def endSession(self):
self.connection.terminate()

View File

@@ -22,247 +22,115 @@
import bb
import bb.event
import itertools
import logging
import multiprocessing
import threading
import array
import os
import signal
import sys
import time
import select
import socket
import subprocess
import errno
import re
import datetime
import bb.server.xmlrpcserver
from bb import daemonize
from multiprocessing import queues
from queue import Empty
from multiprocessing import Event, Process, util, Queue, Pipe, queues, Manager
from . import BitBakeBaseServer, BitBakeBaseServerConnection, BaseImplServer
logger = logging.getLogger('BitBake')
class ProcessTimeout(SystemExit):
pass
class ServerCommunicator():
def __init__(self, connection, event_handle, server):
self.connection = connection
self.event_handle = event_handle
self.server = server
class ProcessServer(multiprocessing.Process):
def runCommand(self, command):
# @todo try/except
self.connection.send(command)
if not self.server.is_alive():
raise SystemExit
while True:
# don't let the user ctrl-c while we're waiting for a response
try:
for idx in range(0,4): # 0, 1, 2, 3
if self.connection.poll(5):
return self.connection.recv()
else:
bb.warn("Timeout while attempting to communicate with bitbake server")
bb.fatal("Gave up; Too many tries: timeout while attempting to communicate with bitbake server")
except KeyboardInterrupt:
pass
def getEventHandle(self):
return self.event_handle.value
class EventAdapter():
"""
Adapter to wrap our event queue since the caller (bb.event) expects to
call a send() method, but our actual queue only has put()
"""
def __init__(self, queue):
self.queue = queue
def send(self, event):
try:
self.queue.put(event)
except Exception as err:
print("EventAdapter puked: %s" % str(err))
class ProcessServer(Process, BaseImplServer):
profile_filename = "profile.log"
profile_processed_filename = "profile.log.processed"
def __init__(self, lock, sock, sockname):
multiprocessing.Process.__init__(self)
self.command_channel = False
self.command_channel_reply = False
def __init__(self, command_channel, event_queue, featurelist):
BaseImplServer.__init__(self)
Process.__init__(self)
self.command_channel = command_channel
self.event_queue = event_queue
self.event = EventAdapter(event_queue)
self.featurelist = featurelist
self.quit = False
self.heartbeat_seconds = 1 # default, BB_HEARTBEAT_EVENT will be checked once we have a datastore.
self.next_heartbeat = time.time()
self.event_handle = None
self.haveui = False
self.lastui = False
self.xmlrpc = False
self._idlefuns = {}
self.bitbake_lock = lock
self.sock = sock
self.sockname = sockname
def register_idle_function(self, function, data):
"""Register a function to be called while the server is idle"""
assert hasattr(function, '__call__')
self._idlefuns[function] = data
self.quitin, self.quitout = Pipe()
self.event_handle = multiprocessing.Value("i")
def run(self):
for event in bb.event.ui_queue:
self.event_queue.put(event)
self.event_handle.value = bb.event.register_UIHhandler(self, True)
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)
try:
self.bitbake_lock.seek(0)
self.bitbake_lock.truncate()
if self.xmlrpc:
self.bitbake_lock.write("%s %s:%s\n" % (os.getpid(), self.xmlrpc.host, self.xmlrpc.port))
else:
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))
pass
if self.cooker.configuration.profile:
try:
import cProfile as profile
except:
import profile
prof = profile.Profile()
ret = profile.Profile.runcall(prof, self.main)
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")
else:
ret = self.main()
return ret
bb.cooker.server_main(self.cooker, self.main)
def main(self):
self.cooker.pre_serve()
# Ignore SIGINT within the server, as all SIGINT handling is done by
# the UI and communicated to us
self.quitin.close()
signal.signal(signal.SIGINT, signal.SIG_IGN)
bb.utils.set_process_name("Cooker")
ready = []
self.controllersock = False
fds = [self.sock]
if self.xmlrpc:
fds.append(self.xmlrpc)
print("Entering server connection loop")
def disconnect_client(self, fds):
if not self.haveui:
return
print("Disconnecting Client")
fds.remove(self.controllersock)
fds.remove(self.command_channel)
bb.event.unregister_UIHhandler(self.event_handle, True)
self.command_channel_reply.writer.close()
self.event_writer.writer.close()
del self.event_writer
self.controllersock.close()
self.controllersock = False
self.haveui = False
self.lastui = time.time()
self.cooker.clientComplete()
if self.timeout is None:
print("No timeout, exiting.")
self.quit = True
while not self.quit:
if self.sock in ready:
self.controllersock, address = self.sock.accept()
if self.haveui:
print("Dropping connection attempt as we have a UI %s" % (str(ready)))
self.controllersock.close()
else:
print("Accepting %s" % (str(ready)))
fds.append(self.controllersock)
if self.controllersock in ready:
try:
print("Connecting Client")
ui_fds = recvfds(self.controllersock, 3)
# Where to write events to
writer = ConnectionWriter(ui_fds[0])
self.event_handle = bb.event.register_UIHhandler(writer, True)
self.event_writer = writer
# Where to read commands from
reader = ConnectionReader(ui_fds[1])
fds.append(reader)
self.command_channel = reader
# Where to send command return values to
writer = ConnectionWriter(ui_fds[2])
self.command_channel_reply = writer
self.haveui = True
except (EOFError, OSError):
disconnect_client(self, fds)
if not self.timeout == -1.0 and not self.haveui and self.lastui and self.timeout and \
(self.lastui + self.timeout) < time.time():
print("Server timeout, exiting.")
self.quit = True
if self.command_channel in ready:
try:
command = self.command_channel.get()
except EOFError:
# Client connection shutting down
ready = []
disconnect_client(self, fds)
continue
if command[0] == "terminateServer":
try:
if self.command_channel.poll():
command = self.command_channel.recv()
self.runCommand(command)
if self.quitout.poll():
self.quitout.recv()
self.quit = True
continue
try:
print("Running command %s" % command)
self.command_channel_reply.send(self.cooker.command.runCommand(command))
except Exception as 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()
ready = self.idle_commands(.1, fds)
print("Exiting")
# Remove the socket file so we don't get any more connections to avoid races
os.unlink(self.sockname)
self.sock.close()
try:
self.cooker.shutdown(True)
self.cooker.notifier.stop()
self.cooker.confignotifier.stop()
except:
pass
self.cooker.post_serve()
# Finally release the lockfile but warn about other processes holding it open
lock = self.bitbake_lock
lockfile = lock.name
lock.close()
lock = None
while not lock:
with bb.utils.timeout(3):
lock = bb.utils.lockfile(lockfile, shared=False, retry=False, block=True)
if not lock:
# Some systems may not have lsof available
procs = None
try:
procs = subprocess.check_output(["lsof", '-w', lockfile], stderr=subprocess.STDOUT)
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
self.runCommand(["stateForceShutdown"])
except:
pass
msg = "Delaying shutdown due to active processes which appear to be holding bitbake.lock"
if procs:
msg += ":\n%s" % str(procs)
print(msg)
return
# We hold the lock so we can remove the file (hide stale pid data)
bb.utils.remove(lockfile)
bb.utils.unlockfile(lock)
self.idle_commands(.1, [self.command_channel, self.quitout])
except Exception:
logger.exception('Running command %s', command)
self.event_queue.close()
bb.event.unregister_UIHhandler(self.event_handle.value)
self.command_channel.close()
self.cooker.shutdown(True)
self.quitout.close()
def idle_commands(self, delay, fds=None):
nextsleep = delay
@@ -292,333 +160,109 @@ class ProcessServer(multiprocessing.Process):
del self._idlefuns[function]
self.quit = True
# Create new heartbeat event?
now = time.time()
if now >= self.next_heartbeat:
# We might have missed heartbeats. Just trigger once in
# that case and continue after the usual delay.
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 nextsleep and now + nextsleep > self.next_heartbeat:
# Shorten timeout so that we we wake up in time for
# the heartbeat.
nextsleep = self.next_heartbeat - now
if nextsleep is not None:
if self.xmlrpc:
nextsleep = self.xmlrpc.get_timeout(nextsleep)
try:
return select.select(fds,[],[],nextsleep)[0]
except InterruptedError:
# Ignore EINTR
return []
else:
return select.select(fds,[],[],0)[0]
class ServerCommunicator():
def __init__(self, connection, recv):
self.connection = connection
self.recv = recv
select.select(fds,[],[],nextsleep)
def runCommand(self, command):
self.connection.send(command)
if not self.recv.poll(30):
raise ProcessTimeout("Timeout while waiting for a reply from the bitbake server")
return self.recv.get()
"""
Run a cooker command on the server
"""
self.command_channel.send(self.cooker.command.runCommand(command))
def updateFeatureSet(self, featureset):
_, error = self.runCommand(["setFeatures", featureset])
def stop(self):
self.quitin.send("quit")
self.quitin.close()
class BitBakeProcessServerConnection(BitBakeBaseServerConnection):
def __init__(self, serverImpl, ui_channel, event_queue):
self.procserver = serverImpl
self.ui_channel = ui_channel
self.event_queue = event_queue
self.connection = ServerCommunicator(self.ui_channel, self.procserver.event_handle, self.procserver)
self.events = self.event_queue
self.terminated = False
def sigterm_terminate(self):
bb.error("UI received SIGTERM")
self.terminate()
def terminate(self):
if self.terminated:
return
self.terminated = True
def flushevents():
while True:
try:
event = self.event_queue.get(block=False)
except (Empty, IOError):
break
if isinstance(event, logging.LogRecord):
logger.handle(event)
signal.signal(signal.SIGINT, signal.SIG_IGN)
self.procserver.stop()
while self.procserver.is_alive():
flushevents()
self.procserver.join(0.1)
self.ui_channel.close()
self.event_queue.close()
self.event_queue.setexit()
# Wrap Queue to provide API which isn't server implementation specific
class ProcessEventQueue(multiprocessing.queues.Queue):
def __init__(self, maxsize):
multiprocessing.queues.Queue.__init__(self, maxsize, ctx=multiprocessing.get_context())
self.exit = False
bb.utils.set_process_name("ProcessEQueue")
def setexit(self):
self.exit = True
def waitEvent(self, timeout):
if self.exit:
return self.getEvent()
try:
if not self.server.is_alive():
return self.getEvent()
return self.get(True, timeout)
except Empty:
return None
def getEvent(self):
try:
if not self.server.is_alive():
self.setexit()
return self.get(False)
except Empty:
if self.exit:
sys.exit(1)
return None
class BitBakeServer(BitBakeBaseServer):
def initServer(self, single_use=True):
# establish communication channels. We use bidirectional pipes for
# ui <--> server command/response pairs
# and a queue for server -> ui event notifications
#
self.ui_channel, self.server_channel = Pipe()
self.event_queue = ProcessEventQueue(0)
self.serverImpl = ProcessServer(self.server_channel, self.event_queue, None)
self.event_queue.server = self.serverImpl
def detach(self):
self.serverImpl.start()
return
def establishConnection(self, featureset):
self.connection = BitBakeProcessServerConnection(self.serverImpl, self.ui_channel, self.event_queue)
_, error = self.connection.connection.runCommand(["setFeatures", featureset])
if error:
logger.error("Unable to set the cooker to the correct featureset: %s" % error)
raise BaseException(error)
def getEventHandle(self):
handle, error = self.runCommand(["getUIHandlerNum"])
if error:
logger.error("Unable to get UI Handler Number: %s" % error)
raise BaseException(error)
return handle
def terminateServer(self):
self.connection.send(['terminateServer'])
return
class BitBakeProcessServerConnection(object):
def __init__(self, ui_channel, recv, eq, sock):
self.connection = ServerCommunicator(ui_channel, recv)
self.events = eq
# Save sock so it doesn't get gc'd for the life of our connection
self.socket_connection = sock
def terminate(self):
self.socket_connection.close()
self.connection.connection.close()
self.connection.recv.close()
return
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):
self.configuration = configuration
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)
self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# AF_UNIX has path length issues so chdir here to workaround
cwd = os.getcwd()
logfile = os.path.join(cwd, "bitbake-cookerdaemon.log")
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()
ready = ConnectionReader(self.readypipe)
r = ready.poll(30)
if r:
r = ready.get()
if not r or r != "ready":
ready.close()
bb.error("Unable to start bitbake server")
if os.path.exists(logfile):
logstart_re = re.compile(self.start_log_format % ('([0-9]+)', '([0-9-]+ [0-9:.]+)'))
started = False
lines = []
with open(logfile, "r") as f:
for line in f:
if started:
lines.append(line)
else:
res = logstart_re.match(line.rstrip())
if res:
ldatetime = datetime.datetime.strptime(res.group(2), self.start_log_datetime_format)
if ldatetime >= startdatetime:
started = True
lines.append(line)
if lines:
if len(lines) > 10:
bb.error("Last 10 lines of server log for this session (%s):\n%s" % (logfile, "".join(lines[-10:])))
else:
bb.error("Server log for this session (%s):\n%s" % (logfile, "".join(lines)))
raise SystemExit(1)
ready.close()
os.close(self.readypipein)
def _startServer(self):
print(self.start_log_format % (os.getpid(), datetime.datetime.now().strftime(self.start_log_datetime_format)))
server = ProcessServer(self.bitbake_lock, self.sock, self.sockname)
self.configuration.setServerRegIdleCallback(server.register_idle_function)
writer = ConnectionWriter(self.readypipein)
try:
self.cooker = bb.cooker.BBCooker(self.configuration, self.featureset)
writer.send("ready")
except:
writer.send("fail")
raise
finally:
os.close(self.readypipein)
server.cooker = self.cooker
server.server_timeout = self.configuration.server_timeout
server.xmlrpcinterface = self.configuration.xmlrpcinterface
print("Started bitbake server pid %d" % os.getpid())
server.start()
def connectProcessServer(sockname, featureset):
# Connect to socket
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))
sock.connect(os.path.basename(sockname))
finally:
os.chdir(cwd)
readfd = writefd = readfd1 = writefd1 = readfd2 = writefd2 = None
eq = command_chan_recv = command_chan = None
try:
# Send an fd for the remote to write events to
readfd, writefd = os.pipe()
eq = BBUIEventQueue(readfd)
# Send an fd for the remote to recieve commands from
readfd1, writefd1 = os.pipe()
command_chan = ConnectionWriter(writefd1)
# Send an fd for the remote to write commands results to
readfd2, writefd2 = os.pipe()
command_chan_recv = ConnectionReader(readfd2)
sendfds(sock, [writefd, readfd1, writefd2])
server_connection = BitBakeProcessServerConnection(command_chan, command_chan_recv, eq, sock)
# Close the ends of the pipes we won't use
for i in [writefd, readfd1, writefd2]:
os.close(i)
server_connection.connection.updateFeatureSet(featureset)
except (Exception, SystemExit) as e:
if command_chan_recv:
command_chan_recv.close()
if command_chan:
command_chan.close()
for i in [writefd, readfd1, writefd2]:
try:
os.close(i)
except OSError:
pass
sock.close()
raise
return server_connection
def sendfds(sock, fds):
'''Send an array of fds over an AF_UNIX socket.'''
fds = array.array('i', fds)
msg = bytes([len(fds) % 256])
sock.sendmsg([msg], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fds)])
def recvfds(sock, size):
'''Receive an array of fds over an AF_UNIX socket.'''
a = array.array('i')
bytes_size = a.itemsize * size
msg, ancdata, flags, addr = sock.recvmsg(1, socket.CMSG_LEN(bytes_size))
if not msg and not ancdata:
raise EOFError
try:
if len(ancdata) != 1:
raise RuntimeError('received %d items of ancdata' %
len(ancdata))
cmsg_level, cmsg_type, cmsg_data = ancdata[0]
if (cmsg_level == socket.SOL_SOCKET and
cmsg_type == socket.SCM_RIGHTS):
if len(cmsg_data) % a.itemsize != 0:
raise ValueError
a.frombytes(cmsg_data)
assert len(a) % 256 == msg[0]
return list(a)
except (ValueError, IndexError):
pass
raise RuntimeError('Invalid data received')
class BBUIEventQueue:
def __init__(self, readfd):
self.eventQueue = []
self.eventQueueLock = threading.Lock()
self.eventQueueNotify = threading.Event()
self.reader = ConnectionReader(readfd)
self.t = threading.Thread()
self.t.setDaemon(True)
self.t.run = self.startCallbackHandler
self.t.start()
def getEvent(self):
self.eventQueueLock.acquire()
if len(self.eventQueue) == 0:
self.eventQueueLock.release()
return None
item = self.eventQueue.pop(0)
if len(self.eventQueue) == 0:
self.eventQueueNotify.clear()
self.eventQueueLock.release()
return item
def waitEvent(self, delay):
self.eventQueueNotify.wait(delay)
return self.getEvent()
def queue_event(self, event):
self.eventQueueLock.acquire()
self.eventQueue.append(event)
self.eventQueueNotify.set()
self.eventQueueLock.release()
def send_event(self, event):
self.queue_event(pickle.loads(event))
def startCallbackHandler(self):
bb.utils.set_process_name("UIEventQueue")
while True:
try:
self.reader.wait()
event = self.reader.get()
self.queue_event(event)
except EOFError:
# Easiest way to exit is to close the file descriptor to cause an exit
break
self.reader.close()
class ConnectionReader(object):
def __init__(self, fd):
self.reader = multiprocessing.connection.Connection(fd, writable=False)
self.rlock = multiprocessing.Lock()
def wait(self, timeout=None):
return multiprocessing.connection.wait([self.reader], timeout)
def poll(self, timeout=None):
return self.reader.poll(timeout)
def get(self):
with self.rlock:
res = self.reader.recv_bytes()
return multiprocessing.reduction.ForkingPickler.loads(res)
def fileno(self):
return self.reader.fileno()
def close(self):
return self.reader.close()
class ConnectionWriter(object):
def __init__(self, fd):
self.writer = multiprocessing.connection.Connection(fd, readable=False)
self.wlock = multiprocessing.Lock()
# Why bb.event needs this I have no idea
self.event = self
def send(self, obj):
obj = multiprocessing.reduction.ForkingPickler.dumps(obj)
with self.wlock:
self.writer.send_bytes(obj)
def fileno(self):
return self.writer.fileno()
def close(self):
return self.writer.close()
signal.signal(signal.SIGTERM, lambda i, s: self.connection.sigterm_terminate())
return self.connection

View File

@@ -0,0 +1,422 @@
#
# BitBake XMLRPC Server
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
This module implements an xmlrpc server for BitBake.
Use this by deriving a class from BitBakeXMLRPCServer and then adding
methods which you want to "export" via XMLRPC. If the methods have the
prefix xmlrpc_, then registering those function will happen automatically,
if not, you need to call register_function.
Use register_idle_function() to add a function which the xmlrpc server
calls from within server_forever when no requests are pending. Make sure
that those functions are non-blocking or else you will introduce latency
in the server's main loop.
"""
import os
import sys
import hashlib
import time
import socket
import signal
import threading
import pickle
import inspect
import select
import http.client
import xmlrpc.client
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import bb
from bb import daemonize
from bb.ui import uievent
from . import BitBakeBaseServer, BitBakeBaseServerConnection, BaseImplServer
DEBUG = False
class BBTransport(xmlrpc.client.Transport):
def __init__(self, timeout):
self.timeout = timeout
self.connection_token = None
xmlrpc.client.Transport.__init__(self)
# Modified from default to pass timeout to HTTPConnection
def make_connection(self, host):
#return an existing connection if possible. This allows
#HTTP/1.1 keep-alive.
if self._connection and host == self._connection[0]:
return self._connection[1]
# create a HTTP connection object from a host descriptor
chost, self._extra_headers, x509 = self.get_host_info(host)
#store the host argument along with the connection object
self._connection = host, http.client.HTTPConnection(chost, timeout=self.timeout)
return self._connection[1]
def set_connection_token(self, token):
self.connection_token = token
def send_content(self, h, body):
if self.connection_token:
h.putheader("Bitbake-token", self.connection_token)
xmlrpc.client.Transport.send_content(self, h, body)
def _create_server(host, port, timeout = 60):
t = BBTransport(timeout)
s = xmlrpc.client.ServerProxy("http://%s:%d/" % (host, port), transport=t, allow_none=True, use_builtin_types=True)
return s, t
def check_connection(remote, timeout):
try:
host, port = remote.split(":")
port = int(port)
except Exception as e:
bb.warn("Failed to read remote definition (%s)" % str(e))
raise e
server, _transport = _create_server(host, port, timeout)
try:
ret, err = server.runCommand(['getVariable', 'TOPDIR'])
if err or not ret:
return False
except ConnectionError:
return False
return True
class BitBakeServerCommands():
def __init__(self, server):
self.server = server
self.has_client = False
def registerEventHandler(self, host, port):
"""
Register a remote UI Event Handler
"""
s, t = _create_server(host, port)
# we don't allow connections if the cooker is running
if (self.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.cooker.state)
self.event_handle = bb.event.register_UIHhandler(s, True)
return self.event_handle, 'OK'
def unregisterEventHandler(self, handlerNum):
"""
Unregister a remote UI Event Handler
"""
return bb.event.unregister_UIHhandler(handlerNum)
def runCommand(self, command):
"""
Run a cooker command on the server
"""
return self.cooker.command.runCommand(command, self.server.readonly)
def getEventHandle(self):
return self.event_handle
def terminateServer(self):
"""
Trigger the server to quit
"""
self.server.quit = True
print("Server (cooker) exiting")
return
def addClient(self):
if self.has_client:
return None
token = hashlib.md5(str(time.time()).encode("utf-8")).hexdigest()
self.server.set_connection_token(token)
self.has_client = True
return token
def removeClient(self):
if self.has_client:
self.server.set_connection_token(None)
self.has_client = False
if self.server.single_use:
self.server.quit = True
# This request handler checks if the request has a "Bitbake-token" header
# field (this comes from the client side) and compares it with its internal
# "Bitbake-token" field (this comes from the server). If the two are not
# equal, it is assumed that a client is trying to connect to the server
# while another client is connected to the server. In this case, a 503 error
# ("service unavailable") is returned to the client.
class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def __init__(self, request, client_address, server):
self.server = server
SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server)
def do_POST(self):
try:
remote_token = self.headers["Bitbake-token"]
except:
remote_token = None
if remote_token != self.server.connection_token and remote_token != "observer":
self.report_503()
else:
if remote_token == "observer":
self.server.readonly = True
else:
self.server.readonly = False
SimpleXMLRPCRequestHandler.do_POST(self)
def report_503(self):
self.send_response(503)
response = 'No more client allowed'
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(response)
class XMLRPCProxyServer(BaseImplServer):
""" not a real working server, but a stub for a proxy server connection
"""
def __init__(self, host, port, use_builtin_types=True):
self.host = host
self.port = port
class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
# remove this when you're done with debugging
# allow_reuse_address = True
def __init__(self, interface, single_use=False, idle_timeout=0):
"""
Constructor
"""
BaseImplServer.__init__(self)
self.single_use = single_use
# Use auto port configuration
if (interface[1] == -1):
interface = (interface[0], 0)
SimpleXMLRPCServer.__init__(self, interface,
requestHandler=BitBakeXMLRPCRequestHandler,
logRequests=False, allow_none=True)
self.host, self.port = self.socket.getsockname()
self.connection_token = None
#self.register_introspection_functions()
self.commands = BitBakeServerCommands(self)
self.autoregister_all_functions(self.commands, "")
self.interface = interface
self.time = time.time()
self.idle_timeout = idle_timeout
if idle_timeout:
self.register_idle_function(self.handle_idle_timeout, self)
def addcooker(self, cooker):
BaseImplServer.addcooker(self, cooker)
self.commands.cooker = cooker
def autoregister_all_functions(self, context, prefix):
"""
Convenience method for registering all functions in the scope
of this class that start with a common prefix
"""
methodlist = inspect.getmembers(context, inspect.ismethod)
for name, method in methodlist:
if name.startswith(prefix):
self.register_function(method, name[len(prefix):])
def handle_idle_timeout(self, server, data, abort):
if not abort:
if time.time() - server.time > server.idle_timeout:
server.quit = True
print("Server idle timeout expired")
return []
def serve_forever(self):
# Start the actual XMLRPC server
bb.cooker.server_main(self.cooker, self._serve_forever)
def _serve_forever(self):
"""
Serve Requests. Overloaded to honor a quit command
"""
self.quit = False
while not self.quit:
fds = [self]
nextsleep = 0.1
for function, data in list(self._idlefuns.items()):
retval = None
try:
retval = function(self, data, False)
if retval is False:
del self._idlefuns[function]
elif retval is True:
nextsleep = 0
elif isinstance(retval, float):
if (retval < nextsleep):
nextsleep = retval
else:
fds = fds + retval
except SystemExit:
raise
except:
import traceback
traceback.print_exc()
if retval == None:
# the function execute failed; delete it
del self._idlefuns[function]
pass
socktimeout = self.socket.gettimeout() or nextsleep
socktimeout = min(socktimeout, nextsleep)
# Mirror what BaseServer handle_request would do
try:
fd_sets = select.select(fds, [], [], socktimeout)
if fd_sets[0] and self in fd_sets[0]:
if self.idle_timeout:
self.time = time.time()
self._handle_request_noblock()
except IOError:
# we ignore interrupted calls
pass
# Tell idle functions we're exiting
for function, data in list(self._idlefuns.items()):
try:
retval = function(self, data, True)
except:
pass
self.server_close()
return
def set_connection_token(self, token):
self.connection_token = token
class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
def __init__(self, serverImpl, clientinfo=("localhost", 0), observer_only = False, featureset = None):
self.connection, self.transport = _create_server(serverImpl.host, serverImpl.port)
self.clientinfo = clientinfo
self.serverImpl = serverImpl
self.observer_only = observer_only
if featureset:
self.featureset = featureset
else:
self.featureset = []
def connect(self, token = None):
if token is None:
if self.observer_only:
token = "observer"
else:
token = self.connection.addClient()
if token is None:
return None
self.transport.set_connection_token(token)
return self
def setupEventQueue(self):
self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo)
for event in bb.event.ui_queue:
self.events.queue_event(event)
_, error = self.connection.runCommand(["setFeatures", self.featureset])
if error:
# disconnect the client, we can't make the setFeature work
self.connection.removeClient()
# no need to log it here, the error shall be sent to the client
raise BaseException(error)
def removeClient(self):
if not self.observer_only:
self.connection.removeClient()
def terminate(self):
# Don't wait for server indefinitely
import socket
socket.setdefaulttimeout(2)
try:
self.events.system_quit()
except:
pass
try:
self.connection.removeClient()
except:
pass
class BitBakeServer(BitBakeBaseServer):
def initServer(self, interface = ("localhost", 0),
single_use = False, idle_timeout=0):
self.interface = interface
self.serverImpl = XMLRPCServer(interface, single_use, idle_timeout)
def detach(self):
daemonize.createDaemon(self.serverImpl.serve_forever, "bitbake-cookerdaemon.log")
del self.cooker
def establishConnection(self, featureset):
self.connection = BitBakeXMLRPCServerConnection(self.serverImpl, self.interface, False, featureset)
return self.connection.connect()
def set_connection_token(self, token):
self.connection.transport.set_connection_token(token)
class BitBakeXMLRPCClient(BitBakeBaseServer):
def __init__(self, observer_only = False, token = None):
self.token = token
self.observer_only = observer_only
# if we need extra caches, just tell the server to load them all
pass
def saveConnectionDetails(self, remote):
self.remote = remote
def establishConnection(self, featureset):
# The format of "remote" must be "server:port"
try:
[host, port] = self.remote.split(":")
port = int(port)
except Exception as e:
bb.warn("Failed to read remote definition (%s)" % str(e))
raise e
# We need our IP for the server connection. We get the IP
# by trying to connect with the server
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((host, port))
ip = s.getsockname()[0]
s.close()
except Exception as e:
bb.warn("Could not create socket for %s:%s (%s)" % (host, port, str(e)))
raise e
try:
self.serverImpl = XMLRPCProxyServer(host, port, use_builtin_types=True)
self.connection = BitBakeXMLRPCServerConnection(self.serverImpl, (ip, 0), self.observer_only, featureset)
return self.connection.connect(self.token)
except Exception as e:
bb.warn("Could not connect to server at %s:%s (%s)" % (host, port, str(e)))
raise e
def endSession(self):
self.connection.removeClient()

View File

@@ -1,154 +0,0 @@
#
# BitBake XMLRPC Client Interface
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
import sys
import socket
import http.client
import xmlrpc.client
import bb
from bb.ui import uievent
class BBTransport(xmlrpc.client.Transport):
def __init__(self, timeout):
self.timeout = timeout
self.connection_token = None
xmlrpc.client.Transport.__init__(self)
# Modified from default to pass timeout to HTTPConnection
def make_connection(self, host):
#return an existing connection if possible. This allows
#HTTP/1.1 keep-alive.
if self._connection and host == self._connection[0]:
return self._connection[1]
# create a HTTP connection object from a host descriptor
chost, self._extra_headers, x509 = self.get_host_info(host)
#store the host argument along with the connection object
self._connection = host, http.client.HTTPConnection(chost, timeout=self.timeout)
return self._connection[1]
def set_connection_token(self, token):
self.connection_token = token
def send_content(self, h, body):
if self.connection_token:
h.putheader("Bitbake-token", self.connection_token)
xmlrpc.client.Transport.send_content(self, h, body)
def _create_server(host, port, timeout = 60):
t = BBTransport(timeout)
s = xmlrpc.client.ServerProxy("http://%s:%d/" % (host, port), transport=t, allow_none=True, use_builtin_types=True)
return s, t
def check_connection(remote, timeout):
try:
host, port = remote.split(":")
port = int(port)
except Exception as e:
bb.warn("Failed to read remote definition (%s)" % str(e))
raise e
server, _transport = _create_server(host, port, timeout)
try:
ret, err = server.runCommand(['getVariable', 'TOPDIR'])
if err or not ret:
return False
except ConnectionError:
return False
return True
class BitBakeXMLRPCServerConnection(object):
def __init__(self, host, port, clientinfo=("localhost", 0), observer_only = False, featureset = None):
self.connection, self.transport = _create_server(host, port)
self.clientinfo = clientinfo
self.observer_only = observer_only
if featureset:
self.featureset = featureset
else:
self.featureset = []
self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo)
_, error = self.connection.runCommand(["setFeatures", self.featureset])
if error:
# disconnect the client, we can't make the setFeature work
self.connection.removeClient()
# no need to log it here, the error shall be sent to the client
raise BaseException(error)
def connect(self, token = None):
if token is None:
if self.observer_only:
token = "observer"
else:
token = self.connection.addClient()
if token is None:
return None
self.transport.set_connection_token(token)
return self
def removeClient(self):
if not self.observer_only:
self.connection.removeClient()
def terminate(self):
# Don't wait for server indefinitely
socket.setdefaulttimeout(2)
try:
self.events.system_quit()
except:
pass
try:
self.connection.removeClient()
except:
pass
def connectXMLRPC(remote, featureset, observer_only = False, token = None):
# The format of "remote" must be "server:port"
try:
[host, port] = remote.split(":")
port = int(port)
except Exception as e:
bb.warn("Failed to parse remote definition %s (%s)" % (remote, str(e)))
raise e
# We need our IP for the server connection. We get the IP
# by trying to connect with the server
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((host, port))
ip = s.getsockname()[0]
s.close()
except Exception as e:
bb.warn("Could not create socket for %s:%s (%s)" % (host, port, str(e)))
raise e
try:
connection = BitBakeXMLRPCServerConnection(host, port, (ip, 0), observer_only, featureset)
return connection.connect(token)
except Exception as e:
bb.warn("Could not connect to server at %s:%s (%s)" % (host, port, str(e)))
raise e

View File

@@ -1,158 +0,0 @@
#
# BitBake XMLRPC Server Interface
#
# Copyright (C) 2006 - 2007 Michael 'Mickey' Lauer
# Copyright (C) 2006 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import os
import sys
import hashlib
import time
import inspect
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import bb
# This request handler checks if the request has a "Bitbake-token" header
# field (this comes from the client side) and compares it with its internal
# "Bitbake-token" field (this comes from the server). If the two are not
# equal, it is assumed that a client is trying to connect to the server
# while another client is connected to the server. In this case, a 503 error
# ("service unavailable") is returned to the client.
class BitBakeXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def __init__(self, request, client_address, server):
self.server = server
SimpleXMLRPCRequestHandler.__init__(self, request, client_address, server)
def do_POST(self):
try:
remote_token = self.headers["Bitbake-token"]
except:
remote_token = None
if 0 and remote_token != self.server.connection_token and remote_token != "observer":
self.report_503()
else:
if remote_token == "observer":
self.server.readonly = True
else:
self.server.readonly = False
SimpleXMLRPCRequestHandler.do_POST(self)
def report_503(self):
self.send_response(503)
response = 'No more client allowed'
self.send_header("Content-type", "text/plain")
self.send_header("Content-length", str(len(response)))
self.end_headers()
self.wfile.write(bytes(response, 'utf-8'))
class BitBakeXMLRPCServer(SimpleXMLRPCServer):
# remove this when you're done with debugging
# allow_reuse_address = True
def __init__(self, interface, cooker, parent):
# Use auto port configuration
if (interface[1] == -1):
interface = (interface[0], 0)
SimpleXMLRPCServer.__init__(self, interface,
requestHandler=BitBakeXMLRPCRequestHandler,
logRequests=False, allow_none=True)
self.host, self.port = self.socket.getsockname()
self.interface = interface
self.connection_token = None
self.commands = BitBakeXMLRPCServerCommands(self)
self.register_functions(self.commands, "")
self.cooker = cooker
self.parent = parent
def register_functions(self, context, prefix):
"""
Convenience method for registering all functions in the scope
of this class that start with a common prefix
"""
methodlist = inspect.getmembers(context, inspect.ismethod)
for name, method in methodlist:
if name.startswith(prefix):
self.register_function(method, name[len(prefix):])
def get_timeout(self, delay):
socktimeout = self.socket.gettimeout() or delay
return min(socktimeout, delay)
def handle_requests(self):
self._handle_request_noblock()
class BitBakeXMLRPCServerCommands():
def __init__(self, server):
self.server = server
self.has_client = False
def registerEventHandler(self, host, port):
"""
Register a remote UI Event Handler
"""
s, t = bb.server.xmlrpcclient._create_server(host, port)
# we don't allow connections if the cooker is running
if (self.server.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.server.cooker.state)
self.event_handle = bb.event.register_UIHhandler(s, True)
return self.event_handle, 'OK'
def unregisterEventHandler(self, handlerNum):
"""
Unregister a remote UI Event Handler
"""
ret = bb.event.unregister_UIHhandler(handlerNum, True)
self.event_handle = None
return ret
def runCommand(self, command):
"""
Run a cooker command on the server
"""
return self.server.cooker.command.runCommand(command, self.server.readonly)
def getEventHandle(self):
return self.event_handle
def terminateServer(self):
"""
Trigger the server to quit
"""
self.server.parent.quit = True
print("XMLRPC Server triggering exit")
return
def addClient(self):
if self.server.parent.haveui:
return None
token = hashlib.md5(str(time.time()).encode("utf-8")).hexdigest()
self.server.connection_token = token
self.server.parent.haveui = True
return token
def removeClient(self):
if self.server.parent.haveui:
self.server.connection_token = None
self.server.parent.haveui = False

820
bitbake/lib/bb/shell.py Normal file
View File

@@ -0,0 +1,820 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
##########################################################################
#
# Copyright (C) 2005-2006 Michael 'Mickey' Lauer <mickey@Vanille.de>
# Copyright (C) 2005-2006 Vanille Media
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
##########################################################################
#
# Thanks to:
# * Holger Freyther <zecke@handhelds.org>
# * Justin Patrin <papercrane@reversefold.com>
#
##########################################################################
"""
BitBake Shell
IDEAS:
* list defined tasks per package
* list classes
* toggle force
* command to reparse just one (or more) bbfile(s)
* automatic check if reparsing is necessary (inotify?)
* frontend for bb file manipulation
* more shell-like features:
- output control, i.e. pipe output into grep, sort, etc.
- job control, i.e. bring running commands into background and foreground
* start parsing in background right after startup
* ncurses interface
PROBLEMS:
* force doesn't always work
* readline completion for commands with more than one parameters
"""
##########################################################################
# Import and setup global variables
##########################################################################
from __future__ import print_function
from functools import reduce
try:
set
except NameError:
from sets import Set as set
import sys, os, readline, socket, httplib, urllib, commands, popen2, shlex, Queue, fnmatch
from bb import data, parse, build, cache, taskdata, runqueue, providers as Providers
__version__ = "0.5.3.1"
__credits__ = """BitBake Shell Version %s (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
Type 'help' for more information, press CTRL-D to exit.""" % __version__
cmds = {}
leave_mainloop = False
last_exception = None
cooker = None
parsed = False
debug = os.environ.get( "BBSHELL_DEBUG", "" )
##########################################################################
# Class BitBakeShellCommands
##########################################################################
class BitBakeShellCommands:
"""This class contains the valid commands for the shell"""
def __init__( self, shell ):
"""Register all the commands"""
self._shell = shell
for attr in BitBakeShellCommands.__dict__:
if not attr.startswith( "_" ):
if attr.endswith( "_" ):
command = attr[:-1].lower()
else:
command = attr[:].lower()
method = getattr( BitBakeShellCommands, attr )
debugOut( "registering command '%s'" % command )
# scan number of arguments
usage = getattr( method, "usage", "" )
if usage != "<...>":
numArgs = len( usage.split() )
else:
numArgs = -1
shell.registerCommand( command, method, numArgs, "%s %s" % ( command, usage ), method.__doc__ )
def _checkParsed( self ):
if not parsed:
print("SHELL: This command needs to parse bbfiles...")
self.parse( None )
def _findProvider( self, item ):
self._checkParsed()
# Need to use taskData for this information
preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, cooker.configuration.data, 1 )
if not preferred: preferred = item
try:
lv, lf, pv, pf = Providers.findBestProvider(preferred, cooker.configuration.data, cooker.status)
except KeyError:
if item in cooker.status.providers:
pf = cooker.status.providers[item][0]
else:
pf = None
return pf
def alias( self, params ):
"""Register a new name for a command"""
new, old = params
if not old in cmds:
print("ERROR: Command '%s' not known" % old)
else:
cmds[new] = cmds[old]
print("OK")
alias.usage = "<alias> <command>"
def buffer( self, params ):
"""Dump specified output buffer"""
index = params[0]
print(self._shell.myout.buffer( int( index ) ))
buffer.usage = "<index>"
def buffers( self, params ):
"""Show the available output buffers"""
commands = self._shell.myout.bufferedCommands()
if not commands:
print("SHELL: No buffered commands available yet. Start doing something.")
else:
print("="*35, "Available Output Buffers", "="*27)
for index, cmd in enumerate( commands ):
print("| %s %s" % ( str( index ).ljust( 3 ), cmd ))
print("="*88)
def build( self, params, cmd = "build" ):
"""Build a providee"""
global last_exception
globexpr = params[0]
self._checkParsed()
names = globfilter( cooker.status.pkg_pn, globexpr )
if len( names ) == 0: names = [ globexpr ]
print("SHELL: Building %s" % ' '.join( names ))
td = taskdata.TaskData(cooker.configuration.abort)
localdata = data.createCopy(cooker.configuration.data)
data.update_data(localdata)
data.expandKeys(localdata)
try:
tasks = []
for name in names:
td.add_provider(localdata, cooker.status, name)
providers = td.get_provider(name)
if len(providers) == 0:
raise Providers.NoProvider
tasks.append([name, "do_%s" % cmd])
td.add_unresolved(localdata, cooker.status)
rq = runqueue.RunQueue(cooker, localdata, cooker.status, td, tasks)
rq.prepare_runqueue()
rq.execute_runqueue()
except Providers.NoProvider:
print("ERROR: No Provider")
last_exception = Providers.NoProvider
except runqueue.TaskFailure as fnids:
last_exception = runqueue.TaskFailure
except build.FuncFailed as e:
print("ERROR: Couldn't build '%s'" % names)
last_exception = e
build.usage = "<providee>"
def clean( self, params ):
"""Clean a providee"""
self.build( params, "clean" )
clean.usage = "<providee>"
def compile( self, params ):
"""Execute 'compile' on a providee"""
self.build( params, "compile" )
compile.usage = "<providee>"
def configure( self, params ):
"""Execute 'configure' on a providee"""
self.build( params, "configure" )
configure.usage = "<providee>"
def install( self, params ):
"""Execute 'install' on a providee"""
self.build( params, "install" )
install.usage = "<providee>"
def edit( self, params ):
"""Call $EDITOR on a providee"""
name = params[0]
bbfile = self._findProvider( name )
if bbfile is not None:
os.system( "%s %s" % ( os.environ.get( "EDITOR", "vi" ), bbfile ) )
else:
print("ERROR: Nothing provides '%s'" % name)
edit.usage = "<providee>"
def environment( self, params ):
"""Dump out the outer BitBake environment"""
cooker.showEnvironment()
def exit_( self, params ):
"""Leave the BitBake Shell"""
debugOut( "setting leave_mainloop to true" )
global leave_mainloop
leave_mainloop = True
def fetch( self, params ):
"""Fetch a providee"""
self.build( params, "fetch" )
fetch.usage = "<providee>"
def fileBuild( self, params, cmd = "build" ):
"""Parse and build a .bb file"""
global last_exception
name = params[0]
bf = completeFilePath( name )
print("SHELL: Calling '%s' on '%s'" % ( cmd, bf ))
try:
cooker.buildFile(bf, cmd)
except parse.ParseError:
print("ERROR: Unable to open or parse '%s'" % bf)
except build.FuncFailed as e:
print("ERROR: Couldn't build '%s'" % name)
last_exception = e
fileBuild.usage = "<bbfile>"
def fileClean( self, params ):
"""Clean a .bb file"""
self.fileBuild( params, "clean" )
fileClean.usage = "<bbfile>"
def fileEdit( self, params ):
"""Call $EDITOR on a .bb file"""
name = params[0]
os.system( "%s %s" % ( os.environ.get( "EDITOR", "vi" ), completeFilePath( name ) ) )
fileEdit.usage = "<bbfile>"
def fileRebuild( self, params ):
"""Rebuild (clean & build) a .bb file"""
self.fileBuild( params, "rebuild" )
fileRebuild.usage = "<bbfile>"
def fileReparse( self, params ):
"""(re)Parse a bb file"""
bbfile = params[0]
print("SHELL: Parsing '%s'" % bbfile)
parse.update_mtime( bbfile )
cooker.parser.reparse(bbfile)
if False: #fromCache:
print("SHELL: File has not been updated, not reparsing")
else:
print("SHELL: Parsed")
fileReparse.usage = "<bbfile>"
def abort( self, params ):
"""Toggle abort task execution flag (see bitbake -k)"""
cooker.configuration.abort = not cooker.configuration.abort
print("SHELL: Abort Flag is now '%s'" % repr( cooker.configuration.abort ))
def force( self, params ):
"""Toggle force task execution flag (see bitbake -f)"""
cooker.configuration.force = not cooker.configuration.force
print("SHELL: Force Flag is now '%s'" % repr( cooker.configuration.force ))
def help( self, params ):
"""Show a comprehensive list of commands and their purpose"""
print("="*30, "Available Commands", "="*30)
for cmd in sorted(cmds):
function, numparams, usage, helptext = cmds[cmd]
print("| %s | %s" % (usage.ljust(30), helptext))
print("="*78)
def lastError( self, params ):
"""Show the reason or log that was produced by the last BitBake event exception"""
if last_exception is None:
print("SHELL: No Errors yet (Phew)...")
else:
reason, event = last_exception.args
print("SHELL: Reason for the last error: '%s'" % reason)
if ':' in reason:
msg, filename = reason.split( ':' )
filename = filename.strip()
print("SHELL: Dumping log file for last error:")
try:
print(open( filename ).read())
except IOError:
print("ERROR: Couldn't open '%s'" % filename)
def match( self, params ):
"""Dump all files or providers matching a glob expression"""
what, globexpr = params
if what == "files":
self._checkParsed()
for key in globfilter( cooker.status.pkg_fn, globexpr ): print(key)
elif what == "providers":
self._checkParsed()
for key in globfilter( cooker.status.pkg_pn, globexpr ): print(key)
else:
print("Usage: match %s" % self.print_.usage)
match.usage = "<files|providers> <glob>"
def new( self, params ):
"""Create a new .bb file and open the editor"""
dirname, filename = params
packages = '/'.join( data.getVar( "BBFILES", cooker.configuration.data, 1 ).split('/')[:-2] )
fulldirname = "%s/%s" % ( packages, dirname )
if not os.path.exists( fulldirname ):
print("SHELL: Creating '%s'" % fulldirname)
os.mkdir( fulldirname )
if os.path.exists( fulldirname ) and os.path.isdir( fulldirname ):
if os.path.exists( "%s/%s" % ( fulldirname, filename ) ):
print("SHELL: ERROR: %s/%s already exists" % ( fulldirname, filename ))
return False
print("SHELL: Creating '%s/%s'" % ( fulldirname, filename ))
newpackage = open( "%s/%s" % ( fulldirname, filename ), "w" )
print("""DESCRIPTION = ""
SECTION = ""
AUTHOR = ""
HOMEPAGE = ""
MAINTAINER = ""
LICENSE = "GPL"
PR = "r0"
SRC_URI = ""
#inherit base
#do_configure() {
#
#}
#do_compile() {
#
#}
#do_stage() {
#
#}
#do_install() {
#
#}
""", file=newpackage)
newpackage.close()
os.system( "%s %s/%s" % ( os.environ.get( "EDITOR" ), fulldirname, filename ) )
new.usage = "<directory> <filename>"
def package( self, params ):
"""Execute 'package' on a providee"""
self.build( params, "package" )
package.usage = "<providee>"
def pasteBin( self, params ):
"""Send a command + output buffer to the pastebin at http://rafb.net/paste"""
index = params[0]
contents = self._shell.myout.buffer( int( index ) )
sendToPastebin( "output of " + params[0], contents )
pasteBin.usage = "<index>"
def pasteLog( self, params ):
"""Send the last event exception error log (if there is one) to http://rafb.net/paste"""
if last_exception is None:
print("SHELL: No Errors yet (Phew)...")
else:
reason, event = last_exception.args
print("SHELL: Reason for the last error: '%s'" % reason)
if ':' in reason:
msg, filename = reason.split( ':' )
filename = filename.strip()
print("SHELL: Pasting log file to pastebin...")
file = open( filename ).read()
sendToPastebin( "contents of " + filename, file )
def patch( self, params ):
"""Execute 'patch' command on a providee"""
self.build( params, "patch" )
patch.usage = "<providee>"
def parse( self, params ):
"""(Re-)parse .bb files and calculate the dependency graph"""
cooker.status = cache.CacheData(cooker.caches_array)
ignore = data.getVar("ASSUME_PROVIDED", cooker.configuration.data, 1) or ""
cooker.status.ignored_dependencies = set( ignore.split() )
cooker.handleCollections( data.getVar("BBFILE_COLLECTIONS", cooker.configuration.data, 1) )
(filelist, masked) = cooker.collect_bbfiles()
cooker.parse_bbfiles(filelist, masked, cooker.myProgressCallback)
cooker.buildDepgraph()
global parsed
parsed = True
print()
def reparse( self, params ):
"""(re)Parse a providee's bb file"""
bbfile = self._findProvider( params[0] )
if bbfile is not None:
print("SHELL: Found bbfile '%s' for '%s'" % ( bbfile, params[0] ))
self.fileReparse( [ bbfile ] )
else:
print("ERROR: Nothing provides '%s'" % params[0])
reparse.usage = "<providee>"
def getvar( self, params ):
"""Dump the contents of an outer BitBake environment variable"""
var = params[0]
value = data.getVar( var, cooker.configuration.data, 1 )
print(value)
getvar.usage = "<variable>"
def peek( self, params ):
"""Dump contents of variable defined in providee's metadata"""
name, var = params
bbfile = self._findProvider( name )
if bbfile is not None:
the_data = cache.Cache.loadDataFull(bbfile, cooker.configuration.data)
value = the_data.getVar( var, 1 )
print(value)
else:
print("ERROR: Nothing provides '%s'" % name)
peek.usage = "<providee> <variable>"
def poke( self, params ):
"""Set contents of variable defined in providee's metadata"""
name, var, value = params
bbfile = self._findProvider( name )
if bbfile is not None:
print("ERROR: Sorry, this functionality is currently broken")
#d = cooker.pkgdata[bbfile]
#data.setVar( var, value, d )
# mark the change semi persistant
#cooker.pkgdata.setDirty(bbfile, d)
#print "OK"
else:
print("ERROR: Nothing provides '%s'" % name)
poke.usage = "<providee> <variable> <value>"
def print_( self, params ):
"""Dump all files or providers"""
what = params[0]
if what == "files":
self._checkParsed()
for key in cooker.status.pkg_fn: print(key)
elif what == "providers":
self._checkParsed()
for key in cooker.status.providers: print(key)
else:
print("Usage: print %s" % self.print_.usage)
print_.usage = "<files|providers>"
def python( self, params ):
"""Enter the expert mode - an interactive BitBake Python Interpreter"""
sys.ps1 = "EXPERT BB>>> "
sys.ps2 = "EXPERT BB... "
import code
interpreter = code.InteractiveConsole( dict( globals() ) )
interpreter.interact( "SHELL: Expert Mode - BitBake Python %s\nType 'help' for more information, press CTRL-D to switch back to BBSHELL." % sys.version )
def showdata( self, params ):
"""Execute 'showdata' on a providee"""
cooker.showEnvironment(None, params)
showdata.usage = "<providee>"
def setVar( self, params ):
"""Set an outer BitBake environment variable"""
var, value = params
data.setVar( var, value, cooker.configuration.data )
print("OK")
setVar.usage = "<variable> <value>"
def rebuild( self, params ):
"""Clean and rebuild a .bb file or a providee"""
self.build( params, "clean" )
self.build( params, "build" )
rebuild.usage = "<providee>"
def shell( self, params ):
"""Execute a shell command and dump the output"""
if params != "":
print(commands.getoutput( " ".join( params ) ))
shell.usage = "<...>"
def stage( self, params ):
"""Execute 'stage' on a providee"""
self.build( params, "populate_staging" )
stage.usage = "<providee>"
def status( self, params ):
"""<just for testing>"""
print("-" * 78)
print("building list = '%s'" % cooker.building_list)
print("build path = '%s'" % cooker.build_path)
print("consider_msgs_cache = '%s'" % cooker.consider_msgs_cache)
print("build stats = '%s'" % cooker.stats)
if last_exception is not None: print("last_exception = '%s'" % repr( last_exception.args ))
print("memory output contents = '%s'" % self._shell.myout._buffer)
def test( self, params ):
"""<just for testing>"""
print("testCommand called with '%s'" % params)
def unpack( self, params ):
"""Execute 'unpack' on a providee"""
self.build( params, "unpack" )
unpack.usage = "<providee>"
def which( self, params ):
"""Computes the providers for a given providee"""
# Need to use taskData for this information
item = params[0]
self._checkParsed()
preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, cooker.configuration.data, 1 )
if not preferred: preferred = item
try:
lv, lf, pv, pf = Providers.findBestProvider(preferred, cooker.configuration.data, cooker.status)
except KeyError:
lv, lf, pv, pf = (None,)*4
try:
providers = cooker.status.providers[item]
except KeyError:
print("SHELL: ERROR: Nothing provides", preferred)
else:
for provider in providers:
if provider == pf: provider = " (***) %s" % provider
else: provider = " %s" % provider
print(provider)
which.usage = "<providee>"
##########################################################################
# Common helper functions
##########################################################################
def completeFilePath( bbfile ):
"""Get the complete bbfile path"""
if not cooker.status: return bbfile
if not cooker.status.pkg_fn: return bbfile
for key in cooker.status.pkg_fn:
if key.endswith( bbfile ):
return key
return bbfile
def sendToPastebin( desc, content ):
"""Send content to http://oe.pastebin.com"""
mydata = {}
mydata["lang"] = "Plain Text"
mydata["desc"] = desc
mydata["cvt_tabs"] = "No"
mydata["nick"] = "%s@%s" % ( os.environ.get( "USER", "unknown" ), socket.gethostname() or "unknown" )
mydata["text"] = content
params = urllib.urlencode( mydata )
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
host = "rafb.net"
conn = httplib.HTTPConnection( "%s:80" % host )
conn.request("POST", "/paste/paste.php", params, headers )
response = conn.getresponse()
conn.close()
if response.status == 302:
location = response.getheader( "location" ) or "unknown"
print("SHELL: Pasted to http://%s%s" % ( host, location ))
else:
print("ERROR: %s %s" % ( response.status, response.reason ))
def completer( text, state ):
"""Return a possible readline completion"""
debugOut( "completer called with text='%s', state='%d'" % ( text, state ) )
if state == 0:
line = readline.get_line_buffer()
if " " in line:
line = line.split()
# we are in second (or more) argument
if line[0] in cmds and hasattr( cmds[line[0]][0], "usage" ): # known command and usage
u = getattr( cmds[line[0]][0], "usage" ).split()[0]
if u == "<variable>":
allmatches = cooker.configuration.data.keys()
elif u == "<bbfile>":
if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
else: allmatches = [ x.split("/")[-1] for x in cooker.status.pkg_fn ]
elif u == "<providee>":
if cooker.status.pkg_fn is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
else: allmatches = cooker.status.providers.iterkeys()
else: allmatches = [ "(No tab completion available for this command)" ]
else: allmatches = [ "(No tab completion available for this command)" ]
else:
# we are in first argument
allmatches = cmds.iterkeys()
completer.matches = [ x for x in allmatches if x[:len(text)] == text ]
#print "completer.matches = '%s'" % completer.matches
if len( completer.matches ) > state:
return completer.matches[state]
else:
return None
def debugOut( text ):
if debug:
sys.stderr.write( "( %s )\n" % text )
def columnize( alist, width = 80 ):
"""
A word-wrap function that preserves existing line breaks
and most spaces in the text. Expects that existing line
breaks are posix newlines (\n).
"""
return reduce(lambda line, word, width=width: '%s%s%s' %
(line,
' \n'[(len(line[line.rfind('\n')+1:])
+ len(word.split('\n', 1)[0]
) >= width)],
word),
alist
)
def globfilter( names, pattern ):
return fnmatch.filter( names, pattern )
##########################################################################
# Class MemoryOutput
##########################################################################
class MemoryOutput:
"""File-like output class buffering the output of the last 10 commands"""
def __init__( self, delegate ):
self.delegate = delegate
self._buffer = []
self.text = []
self._command = None
def startCommand( self, command ):
self._command = command
self.text = []
def endCommand( self ):
if self._command is not None:
if len( self._buffer ) == 10: del self._buffer[0]
self._buffer.append( ( self._command, self.text ) )
def removeLast( self ):
if self._buffer:
del self._buffer[ len( self._buffer ) - 1 ]
self.text = []
self._command = None
def lastBuffer( self ):
if self._buffer:
return self._buffer[ len( self._buffer ) -1 ][1]
def bufferedCommands( self ):
return [ cmd for cmd, output in self._buffer ]
def buffer( self, i ):
if i < len( self._buffer ):
return "BB>> %s\n%s" % ( self._buffer[i][0], "".join( self._buffer[i][1] ) )
else: return "ERROR: Invalid buffer number. Buffer needs to be in (0, %d)" % ( len( self._buffer ) - 1 )
def write( self, text ):
if self._command is not None and text != "BB>> ": self.text.append( text )
if self.delegate is not None: self.delegate.write( text )
def flush( self ):
return self.delegate.flush()
def fileno( self ):
return self.delegate.fileno()
def isatty( self ):
return self.delegate.isatty()
##########################################################################
# Class BitBakeShell
##########################################################################
class BitBakeShell:
def __init__( self ):
"""Register commands and set up readline"""
self.commandQ = Queue.Queue()
self.commands = BitBakeShellCommands( self )
self.myout = MemoryOutput( sys.stdout )
self.historyfilename = os.path.expanduser( "~/.bbsh_history" )
self.startupfilename = os.path.expanduser( "~/.bbsh_startup" )
readline.set_completer( completer )
readline.set_completer_delims( " " )
readline.parse_and_bind("tab: complete")
try:
readline.read_history_file( self.historyfilename )
except IOError:
pass # It doesn't exist yet.
print(__credits__)
def cleanup( self ):
"""Write readline history and clean up resources"""
debugOut( "writing command history" )
try:
readline.write_history_file( self.historyfilename )
except:
print("SHELL: Unable to save command history")
def registerCommand( self, command, function, numparams = 0, usage = "", helptext = "" ):
"""Register a command"""
if usage == "": usage = command
if helptext == "": helptext = function.__doc__ or "<not yet documented>"
cmds[command] = ( function, numparams, usage, helptext )
def processCommand( self, command, params ):
"""Process a command. Check number of params and print a usage string, if appropriate"""
debugOut( "processing command '%s'..." % command )
try:
function, numparams, usage, helptext = cmds[command]
except KeyError:
print("SHELL: ERROR: '%s' command is not a valid command." % command)
self.myout.removeLast()
else:
if (numparams != -1) and (not len( params ) == numparams):
print("Usage: '%s'" % usage)
return
result = function( self.commands, params )
debugOut( "result was '%s'" % result )
def processStartupFile( self ):
"""Read and execute all commands found in $HOME/.bbsh_startup"""
if os.path.exists( self.startupfilename ):
startupfile = open( self.startupfilename, "r" )
for cmdline in startupfile:
debugOut( "processing startup line '%s'" % cmdline )
if not cmdline:
continue
if "|" in cmdline:
print("ERROR: '|' in startup file is not allowed. Ignoring line")
continue
self.commandQ.put( cmdline.strip() )
def main( self ):
"""The main command loop"""
while not leave_mainloop:
try:
if self.commandQ.empty():
sys.stdout = self.myout.delegate
cmdline = raw_input( "BB>> " )
sys.stdout = self.myout
else:
cmdline = self.commandQ.get()
if cmdline:
allCommands = cmdline.split( ';' )
for command in allCommands:
pipecmd = None
#
# special case for expert mode
if command == 'python':
sys.stdout = self.myout.delegate
self.processCommand( command, "" )
sys.stdout = self.myout
else:
self.myout.startCommand( command )
if '|' in command: # disable output
command, pipecmd = command.split( '|' )
delegate = self.myout.delegate
self.myout.delegate = None
tokens = shlex.split( command, True )
self.processCommand( tokens[0], tokens[1:] or "" )
self.myout.endCommand()
if pipecmd is not None: # restore output
self.myout.delegate = delegate
pipe = popen2.Popen4( pipecmd )
pipe.tochild.write( "\n".join( self.myout.lastBuffer() ) )
pipe.tochild.close()
sys.stdout.write( pipe.fromchild.read() )
#
except EOFError:
print()
return
except KeyboardInterrupt:
print()
##########################################################################
# Start function - called from the BitBake command line utility
##########################################################################
def start( aCooker ):
global cooker
cooker = aCooker
bbshell = BitBakeShell()
bbshell.processStartupFile()
bbshell.main()
bbshell.cleanup()
if __name__ == "__main__":
print("SHELL: Sorry, this program should only be called by BitBake.")

View File

@@ -5,8 +5,6 @@ import re
import tempfile
import pickle
import bb.data
import difflib
import simplediff
from bb.checksum import FileChecksumCache
logger = logging.getLogger('BitBake.SigGen')
@@ -15,7 +13,7 @@ def init(d):
siggens = [obj for obj in globals().values()
if type(obj) is type and issubclass(obj, SignatureGenerator)]
desired = d.getVar("BB_SIGNATURE_HANDLER") or "noop"
desired = d.getVar("BB_SIGNATURE_HANDLER", True) or "noop"
for sg in siggens:
if desired == sg.name:
return sg(d)
@@ -69,10 +67,6 @@ class SignatureGenerator(object):
def set_taskdata(self, data):
self.runtaskdeps, self.taskhash, self.file_checksum_values, self.taints, self.basehash = data
def reset(self, data):
self.__init__(data)
class SignatureGeneratorBasic(SignatureGenerator):
"""
"""
@@ -88,10 +82,10 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.gendeps = {}
self.lookupcache = {}
self.pkgnameextract = re.compile("(?P<fn>.*)\..*")
self.basewhitelist = set((data.getVar("BB_HASHBASE_WHITELIST") or "").split())
self.basewhitelist = set((data.getVar("BB_HASHBASE_WHITELIST", True) or "").split())
self.taskwhitelist = None
self.init_rundepcheck(data)
checksum_cache_file = data.getVar("BB_HASH_CHECKSUM_CACHE_FILE")
checksum_cache_file = data.getVar("BB_HASH_CHECKSUM_CACHE_FILE", True)
if checksum_cache_file:
self.checksum_cache = FileChecksumCache()
self.checksum_cache.init_cache(data, checksum_cache_file)
@@ -99,7 +93,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.checksum_cache = None
def init_rundepcheck(self, data):
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST") or None
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST", True) or None
if self.taskwhitelist:
self.twl = re.compile(self.taskwhitelist)
else:
@@ -107,7 +101,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
def _build_data(self, fn, d):
ignore_mismatch = ((d.getVar("BB_HASH_IGNORE_MISMATCH") or '') == '1')
tasklist, gendeps, lookupcache = bb.data.generate_dependencies(d)
taskdeps = {}
@@ -142,7 +135,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
data = data + str(var)
datahash = hashlib.md5(data.encode("utf-8")).hexdigest()
k = fn + "." + task
if not ignore_mismatch and k in self.basehash and self.basehash[k] != datahash:
if k in self.basehash and self.basehash[k] != datahash:
bb.error("When reparsing %s, the basehash value changed from %s to %s. The metadata is not deterministic and this needs to be fixed." % (k, self.basehash[k], datahash))
self.basehash[k] = datahash
taskdeps[task] = alldeps
@@ -161,15 +154,13 @@ class SignatureGeneratorBasic(SignatureGenerator):
try:
taskdeps = self._build_data(fn, d)
except bb.parse.SkipRecipe:
raise
except:
bb.warn("Error during finalise of %s" % fn)
raise
#Slow but can be useful for debugging mismatched basehashes
#for task in self.taskdeps[fn]:
# self.dump_sigtask(fn, task, d.getVar("STAMP"), False)
# self.dump_sigtask(fn, task, d.getVar("STAMP", True), False)
for task in taskdeps:
d.setVar("BB_BASEHASH_task-%s" % task, self.basehash[fn + "." + task])
@@ -315,8 +306,8 @@ class SignatureGeneratorBasic(SignatureGenerator):
pass
raise err
def dump_sigfn(self, fn, dataCaches, options):
if fn in self.taskdeps:
def dump_sigs(self, dataCaches, options):
for fn in self.taskdeps:
for task in self.taskdeps[fn]:
tid = fn + ":" + task
(mc, _, _) = bb.runqueue.split_tid(tid)
@@ -354,67 +345,16 @@ class SignatureGeneratorBasicHash(SignatureGeneratorBasic):
def dump_this_task(outfile, d):
import bb.parse
fn = d.getVar("BB_FILENAME")
task = "do_" + d.getVar("BB_CURRENTTASK")
fn = d.getVar("BB_FILENAME", True)
task = "do_" + d.getVar("BB_CURRENTTASK", True)
referencestamp = bb.build.stamp_internal(task, d, None, True)
bb.parse.siggen.dump_sigtask(fn, task, outfile, "customfile:" + referencestamp)
def init_colors(enable_color):
"""Initialise colour dict for passing to compare_sigfiles()"""
# First set up the colours
colors = {'color_title': '\033[1;37;40m',
'color_default': '\033[0;37;40m',
'color_add': '\033[1;32;40m',
'color_remove': '\033[1;31;40m',
}
# Leave all keys present but clear the values
if not enable_color:
for k in colors.keys():
colors[k] = ''
return colors
def worddiff_str(oldstr, newstr, colors=None):
if not colors:
colors = init_colors(False)
diff = simplediff.diff(oldstr.split(' '), newstr.split(' '))
ret = []
for change, value in diff:
value = ' '.join(value)
if change == '=':
ret.append(value)
elif change == '+':
item = '{color_add}{{+{value}+}}{color_default}'.format(value=value, **colors)
ret.append(item)
elif change == '-':
item = '{color_remove}[-{value}-]{color_default}'.format(value=value, **colors)
ret.append(item)
whitespace_note = ''
if oldstr != newstr and ' '.join(oldstr.split()) == ' '.join(newstr.split()):
whitespace_note = ' (whitespace changed)'
return '"%s"%s' % (' '.join(ret), whitespace_note)
def list_inline_diff(oldlist, newlist, colors=None):
if not colors:
colors = init_colors(False)
diff = simplediff.diff(oldlist, newlist)
ret = []
for change, value in diff:
value = ' '.join(value)
if change == '=':
ret.append("'%s'" % value)
elif change == '+':
item = '{color_add}+{value}{color_default}'.format(value=value, **colors)
ret.append(item)
elif change == '-':
item = '{color_remove}-{value}{color_default}'.format(value=value, **colors)
ret.append(item)
return '[%s]' % (', '.join(ret))
def clean_basepath(a):
mc = None
if a.startswith("multiconfig:"):
_, mc, a = a.split(":", 2)
b = a.rsplit("/", 2)[1] + '/' + a.rsplit("/", 2)[2]
b = a.rsplit("/", 2)[1] + a.rsplit("/", 2)[2]
if a.startswith("virtual:"):
b = b + ":" + a.rsplit(":", 1)[0]
if mc:
@@ -433,26 +373,9 @@ def clean_basepaths_list(a):
b.append(clean_basepath(x))
return b
def compare_sigfiles(a, b, recursecb=None, color=False, collapsed=False):
def compare_sigfiles(a, b, recursecb = None):
output = []
colors = init_colors(color)
def color_format(formatstr, **values):
"""
Return colour formatted string.
NOTE: call with the format string, not an already formatted string
containing values (otherwise you could have trouble with { and }
characters)
"""
if not formatstr.endswith('{color_default}'):
formatstr += '{color_default}'
# In newer python 3 versions you can pass both of these directly,
# but we only require 3.4 at the moment
formatparams = {}
formatparams.update(colors)
formatparams.update(values)
return formatstr.format(**formatparams)
with open(a, 'rb') as f:
p1 = pickle.Unpickler(f)
a_data = p1.load()
@@ -506,59 +429,39 @@ def compare_sigfiles(a, b, recursecb=None, color=False, collapsed=False):
return changed, added, removed
if 'basewhitelist' in a_data and a_data['basewhitelist'] != b_data['basewhitelist']:
output.append(color_format("{color_title}basewhitelist changed{color_default} from '%s' to '%s'") % (a_data['basewhitelist'], b_data['basewhitelist']))
output.append("basewhitelist changed from '%s' to '%s'" % (a_data['basewhitelist'], b_data['basewhitelist']))
if a_data['basewhitelist'] and b_data['basewhitelist']:
output.append("changed items: %s" % a_data['basewhitelist'].symmetric_difference(b_data['basewhitelist']))
if 'taskwhitelist' in a_data and a_data['taskwhitelist'] != b_data['taskwhitelist']:
output.append(color_format("{color_title}taskwhitelist changed{color_default} from '%s' to '%s'") % (a_data['taskwhitelist'], b_data['taskwhitelist']))
output.append("taskwhitelist changed from '%s' to '%s'" % (a_data['taskwhitelist'], b_data['taskwhitelist']))
if a_data['taskwhitelist'] and b_data['taskwhitelist']:
output.append("changed items: %s" % a_data['taskwhitelist'].symmetric_difference(b_data['taskwhitelist']))
if a_data['taskdeps'] != b_data['taskdeps']:
output.append(color_format("{color_title}Task dependencies changed{color_default} from:\n%s\nto:\n%s") % (sorted(a_data['taskdeps']), sorted(b_data['taskdeps'])))
output.append("Task dependencies changed from:\n%s\nto:\n%s" % (sorted(a_data['taskdeps']), sorted(b_data['taskdeps'])))
if a_data['basehash'] != b_data['basehash'] and not collapsed:
output.append(color_format("{color_title}basehash changed{color_default} from %s to %s") % (a_data['basehash'], b_data['basehash']))
if a_data['basehash'] != b_data['basehash']:
output.append("basehash changed from %s to %s" % (a_data['basehash'], b_data['basehash']))
changed, added, removed = dict_diff(a_data['gendeps'], b_data['gendeps'], a_data['basewhitelist'] & b_data['basewhitelist'])
if changed:
for dep in changed:
output.append(color_format("{color_title}List of dependencies for variable %s changed from '{color_default}%s{color_title}' to '{color_default}%s{color_title}'") % (dep, a_data['gendeps'][dep], b_data['gendeps'][dep]))
output.append("List of dependencies for variable %s changed from '%s' to '%s'" % (dep, a_data['gendeps'][dep], b_data['gendeps'][dep]))
if a_data['gendeps'][dep] and b_data['gendeps'][dep]:
output.append("changed items: %s" % a_data['gendeps'][dep].symmetric_difference(b_data['gendeps'][dep]))
if added:
for dep in added:
output.append(color_format("{color_title}Dependency on variable %s was added") % (dep))
output.append("Dependency on variable %s was added" % (dep))
if removed:
for dep in removed:
output.append(color_format("{color_title}Dependency on Variable %s was removed") % (dep))
output.append("Dependency on Variable %s was removed" % (dep))
changed, added, removed = dict_diff(a_data['varvals'], b_data['varvals'])
if changed:
for dep in changed:
oldval = a_data['varvals'][dep]
newval = b_data['varvals'][dep]
if newval and oldval and ('\n' in oldval or '\n' in newval):
diff = difflib.unified_diff(oldval.splitlines(), newval.splitlines(), lineterm='')
# Cut off the first two lines, since we aren't interested in
# the old/new filename (they are blank anyway in this case)
difflines = list(diff)[2:]
if color:
# Add colour to diff output
for i, line in enumerate(difflines):
if line.startswith('+'):
line = color_format('{color_add}{line}', line=line)
difflines[i] = line
elif line.startswith('-'):
line = color_format('{color_remove}{line}', line=line)
difflines[i] = line
output.append(color_format("{color_title}Variable {var} value changed:{color_default}\n{diff}", var=dep, diff='\n'.join(difflines)))
elif newval and oldval and (' ' in oldval or ' ' in newval):
output.append(color_format("{color_title}Variable {var} value changed:{color_default}\n{diff}", var=dep, diff=worddiff_str(oldval, newval, colors)))
else:
output.append(color_format("{color_title}Variable {var} value changed from '{color_default}{oldval}{color_title}' to '{color_default}{newval}{color_title}'{color_default}", var=dep, oldval=oldval, newval=newval))
output.append("Variable %s value changed from '%s' to '%s'" % (dep, a_data['varvals'][dep], b_data['varvals'][dep]))
if not 'file_checksum_values' in a_data:
a_data['file_checksum_values'] = {}
@@ -568,38 +471,32 @@ def compare_sigfiles(a, b, recursecb=None, color=False, collapsed=False):
changed, added, removed = file_checksums_diff(a_data['file_checksum_values'], b_data['file_checksum_values'])
if changed:
for f, old, new in changed:
output.append(color_format("{color_title}Checksum for file %s changed{color_default} from %s to %s") % (f, old, new))
output.append("Checksum for file %s changed from %s to %s" % (f, old, new))
if added:
for f in added:
output.append(color_format("{color_title}Dependency on checksum of file %s was added") % (f))
output.append("Dependency on checksum of file %s was added" % (f))
if removed:
for f in removed:
output.append(color_format("{color_title}Dependency on checksum of file %s was removed") % (f))
output.append("Dependency on checksum of file %s was removed" % (f))
if not 'runtaskdeps' in a_data:
a_data['runtaskdeps'] = {}
if not 'runtaskdeps' in b_data:
b_data['runtaskdeps'] = {}
if not collapsed:
if len(a_data['runtaskdeps']) != len(b_data['runtaskdeps']):
changed = ["Number of task dependencies changed"]
else:
changed = []
for idx, task in enumerate(a_data['runtaskdeps']):
a = a_data['runtaskdeps'][idx]
b = b_data['runtaskdeps'][idx]
if a_data['runtaskhashes'][a] != b_data['runtaskhashes'][b] and not collapsed:
changed.append("%s with hash %s\n changed to\n%s with hash %s" % (clean_basepath(a), a_data['runtaskhashes'][a], clean_basepath(b), b_data['runtaskhashes'][b]))
if len(a_data['runtaskdeps']) != len(b_data['runtaskdeps']):
changed = ["Number of task dependencies changed"]
else:
changed = []
for idx, task in enumerate(a_data['runtaskdeps']):
a = a_data['runtaskdeps'][idx]
b = b_data['runtaskdeps'][idx]
if a_data['runtaskhashes'][a] != b_data['runtaskhashes'][b]:
changed.append("%s with hash %s\n changed to\n%s with hash %s" % (a, a_data['runtaskhashes'][a], b, b_data['runtaskhashes'][b]))
if changed:
clean_a = clean_basepaths_list(a_data['runtaskdeps'])
clean_b = clean_basepaths_list(b_data['runtaskdeps'])
if clean_a != clean_b:
output.append(color_format("{color_title}runtaskdeps changed:{color_default}\n%s") % list_inline_diff(clean_a, clean_b, colors))
else:
output.append(color_format("{color_title}runtaskdeps changed:"))
output.append("\n".join(changed))
if changed:
output.append("runtaskdeps changed from %s to %s" % (clean_basepaths_list(a_data['runtaskdeps']), clean_basepaths_list(b_data['runtaskdeps'])))
output.append("\n".join(changed))
if 'runtaskhashes' in a_data and 'runtaskhashes' in b_data:
@@ -615,7 +512,7 @@ def compare_sigfiles(a, b, recursecb=None, color=False, collapsed=False):
#output.append("Dependency on task %s was replaced by %s with same hash" % (dep, bdep))
bdep_found = True
if not bdep_found:
output.append(color_format("{color_title}Dependency on task %s was added{color_default} with hash %s") % (clean_basepath(dep), b[dep]))
output.append("Dependency on task %s was added with hash %s" % (clean_basepath(dep), b[dep]))
if removed:
for dep in removed:
adep_found = False
@@ -625,25 +522,21 @@ def compare_sigfiles(a, b, recursecb=None, color=False, collapsed=False):
#output.append("Dependency on task %s was replaced by %s with same hash" % (adep, dep))
adep_found = True
if not adep_found:
output.append(color_format("{color_title}Dependency on task %s was removed{color_default} with hash %s") % (clean_basepath(dep), a[dep]))
output.append("Dependency on task %s was removed with hash %s" % (clean_basepath(dep), a[dep]))
if changed:
for dep in changed:
if not collapsed:
output.append(color_format("{color_title}Hash for dependent task %s changed{color_default} from %s to %s") % (clean_basepath(dep), a[dep], b[dep]))
output.append("Hash for dependent task %s changed from %s to %s" % (clean_basepath(dep), a[dep], b[dep]))
if callable(recursecb):
# If a dependent hash changed, might as well print the line above and then defer to the changes in
# that hash since in all likelyhood, they're the same changes this task also saw.
recout = recursecb(dep, a[dep], b[dep])
if recout:
if collapsed:
output.extend(recout)
else:
# If a dependent hash changed, might as well print the line above and then defer to the changes in
# that hash since in all likelyhood, they're the same changes this task also saw.
output = [output[-1]] + recout
output = [output[-1]] + recout
a_taint = a_data.get('taint', None)
b_taint = b_data.get('taint', None)
if a_taint != b_taint:
output.append(color_format("{color_title}Taint (by forced/invalidated task) changed{color_default} from %s to %s") % (a_taint, b_taint))
output.append("Taint (by forced/invalidated task) changed from %s to %s" % (a_taint, b_taint))
return output
@@ -671,8 +564,7 @@ def calc_taskhash(sigdata):
data = data + sigdata['runtaskhashes'][dep]
for c in sigdata['file_checksum_values']:
if c[1]:
data = data + c[1]
data = data + c[1]
if 'taint' in sigdata:
if 'nostamp:' in sigdata['taint']:

View File

@@ -47,7 +47,7 @@ class TaskData:
"""
BitBake Task Data implementation
"""
def __init__(self, abort = True, skiplist = None, allowincomplete = False):
def __init__(self, abort = True, tryaltconfigs = False, skiplist = None, allowincomplete = False):
self.build_targets = {}
self.run_targets = {}
@@ -66,6 +66,7 @@ class TaskData:
self.failed_fns = []
self.abort = abort
self.tryaltconfigs = tryaltconfigs
self.allowincomplete = allowincomplete
self.skiplist = skiplist
@@ -88,19 +89,6 @@ class TaskData:
self.add_extra_deps(fn, dataCache)
# Common code for dep_name/depends = 'depends'/idepends and 'rdepends'/irdepends
def handle_deps(task, dep_name, depends, seen):
if dep_name in task_deps and task in task_deps[dep_name]:
ids = []
for dep in task_deps[dep_name][task].split():
if dep:
parts = dep.split(":")
if len(parts) != 2:
bb.msg.fatal("TaskData", "Error for %s:%s[%s], dependency %s in '%s' does not contain exactly one ':' character.\n Task '%s' should be specified in the form 'packagename:task'" % (fn, task, dep_name, dep, task_deps[dep_name][task], dep_name))
ids.append((parts[0], parts[1]))
seen(parts[0])
depends.extend(ids)
for task in task_deps['tasks']:
tid = "%s:%s" % (fn, task)
@@ -117,8 +105,24 @@ class TaskData:
self.taskentries[tid].tdepends.extend(parentids)
# Touch all intertask dependencies
handle_deps(task, 'depends', self.taskentries[tid].idepends, self.seen_build_target)
handle_deps(task, 'rdepends', self.taskentries[tid].irdepends, self.seen_run_target)
if 'depends' in task_deps and task in task_deps['depends']:
ids = []
for dep in task_deps['depends'][task].split():
if dep:
if ":" not in dep:
bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'depends' should be specified in the form 'packagename:task'" % (fn, dep))
ids.append(((dep.split(":")[0]), dep.split(":")[1]))
self.seen_build_target(dep.split(":")[0])
self.taskentries[tid].idepends.extend(ids)
if 'rdepends' in task_deps and task in task_deps['rdepends']:
ids = []
for dep in task_deps['rdepends'][task].split():
if dep:
if ":" not in dep:
bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'rdepends' should be specified in the form 'packagename:task'" % (fn, dep))
ids.append(((dep.split(":")[0]), dep.split(":")[1]))
self.seen_run_target(dep.split(":")[0])
self.taskentries[tid].irdepends.extend(ids)
# Work out build dependencies
if not fn in self.depids:

View File

@@ -49,9 +49,6 @@ class ReferenceTest(unittest.TestCase):
def assertExecs(self, execs):
self.assertEqual(self.execs, execs)
def assertContains(self, contains):
self.assertEqual(self.contains, contains)
class VariableReferenceTest(ReferenceTest):
def parseExpression(self, exp):
@@ -71,7 +68,7 @@ class VariableReferenceTest(ReferenceTest):
def test_python_reference(self):
self.setEmptyVars(["BAR"])
self.parseExpression("${@d.getVar('BAR') + 'foo'}")
self.parseExpression("${@bb.data.getVar('BAR', d, True) + 'foo'}")
self.assertReferences(set(["BAR"]))
class ShellReferenceTest(ReferenceTest):
@@ -204,7 +201,6 @@ class PythonReferenceTest(ReferenceTest):
self.references = parsedvar.references | parser.references
self.execs = parser.execs
self.contains = parser.contains
@staticmethod
def indent(value):
@@ -213,17 +209,17 @@ be. These unit tests are testing snippets."""
return " " + value
def test_getvar_reference(self):
self.parseExpression("d.getVar('foo')")
self.parseExpression("bb.data.getVar('foo', d, True)")
self.assertReferences(set(["foo"]))
self.assertExecs(set())
def test_getvar_computed_reference(self):
self.parseExpression("d.getVar('f' + 'o' + 'o')")
self.parseExpression("bb.data.getVar('f' + 'o' + 'o', d, True)")
self.assertReferences(set())
self.assertExecs(set())
def test_getvar_exec_reference(self):
self.parseExpression("eval('d.getVar(\"foo\")')")
self.parseExpression("eval('bb.data.getVar(\"foo\", d, True)')")
self.assertReferences(set())
self.assertExecs(set(["eval"]))
@@ -269,35 +265,15 @@ be. These unit tests are testing snippets."""
self.assertExecs(set(["testget"]))
del self.context["testget"]
def test_contains(self):
self.parseExpression('bb.utils.contains("TESTVAR", "one", "true", "false", d)')
self.assertContains({'TESTVAR': {'one'}})
def test_contains_multi(self):
self.parseExpression('bb.utils.contains("TESTVAR", "one two", "true", "false", d)')
self.assertContains({'TESTVAR': {'one two'}})
def test_contains_any(self):
self.parseExpression('bb.utils.contains_any("TESTVAR", "hello", "true", "false", d)')
self.assertContains({'TESTVAR': {'hello'}})
def test_contains_any_multi(self):
self.parseExpression('bb.utils.contains_any("TESTVAR", "one two three", "true", "false", d)')
self.assertContains({'TESTVAR': {'one', 'two', 'three'}})
def test_contains_filter(self):
self.parseExpression('bb.utils.filter("TESTVAR", "hello there world", d)')
self.assertContains({'TESTVAR': {'hello', 'there', 'world'}})
class DependencyReferenceTest(ReferenceTest):
pydata = """
d.getVar('somevar')
bb.data.getVar('somevar', d, True)
def test(d):
foo = 'bar %s' % 'foo'
def test2(d):
d.getVar(foo)
d.getVar(foo, True)
d.getVar('bar', False)
test2(d)
@@ -309,9 +285,9 @@ def a():
test(d)
d.expand(d.getVar("something", False))
d.expand("${inexpand} somethingelse")
d.getVar(a(), False)
bb.data.expand(bb.data.getVar("something", False, d), d)
bb.data.expand("${inexpand} somethingelse", d)
bb.data.getVar(a(), d, False)
"""
def test_python(self):
@@ -394,30 +370,6 @@ esac
self.assertEqual(deps, set(["oe_libinstall"]))
def test_contains_vardeps(self):
expr = '${@bb.utils.filter("TESTVAR", "somevalue anothervalue", d)} \
${@bb.utils.contains("TESTVAR", "testval testval2", "yetanothervalue", "", d)} \
${@bb.utils.contains("TESTVAR", "testval2 testval3", "blah", "", d)} \
${@bb.utils.contains_any("TESTVAR", "testval2 testval3", "lastone", "", d)}'
parsedvar = self.d.expandWithRefs(expr, None)
# Check contains
self.assertEqual(parsedvar.contains, {'TESTVAR': {'testval2 testval3', 'anothervalue', 'somevalue', 'testval testval2', 'testval2', 'testval3'}})
# Check dependencies
self.d.setVar('ANOTHERVAR', expr)
self.d.setVar('TESTVAR', 'anothervalue testval testval2')
deps, values = bb.data.build_dependencies("ANOTHERVAR", set(self.d.keys()), set(), set(), self.d)
self.assertEqual(sorted(values.splitlines()),
sorted([expr,
'TESTVAR{anothervalue} = Set',
'TESTVAR{somevalue} = Unset',
'TESTVAR{testval testval2} = Set',
'TESTVAR{testval2 testval3} = Unset',
'TESTVAR{testval2} = Set',
'TESTVAR{testval3} = Unset'
]))
# Check final value
self.assertEqual(self.d.getVar('ANOTHERVAR').split(), ['anothervalue', 'yetanothervalue', 'lastone'])
#Currently no wildcard support
#def test_vardeps_wildcards(self):
# self.d.setVar("oe_libinstall", "echo test")

View File

@@ -77,13 +77,13 @@ class DataExpansions(unittest.TestCase):
self.assertEqual(str(val), "boo value_of_foo")
def test_python_snippet_getvar(self):
val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
self.assertEqual(str(val), "value_of_foo value_of_bar")
def test_python_unexpanded(self):
self.d.setVar("bar", "${unsetvar}")
val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
self.assertEqual(str(val), "${@d.getVar('foo') + ' ${unsetvar}'}")
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
self.assertEqual(str(val), "${@d.getVar('foo', True) + ' ${unsetvar}'}")
def test_python_snippet_syntax_error(self):
self.d.setVar("FOO", "${@foo = 5}")
@@ -99,7 +99,7 @@ class DataExpansions(unittest.TestCase):
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
def test_value_containing_value(self):
val = self.d.expand("${@d.getVar('foo') + ' ${bar}'}")
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
self.assertEqual(str(val), "value_of_foo value_of_bar")
def test_reference_undefined_var(self):
@@ -109,7 +109,7 @@ class DataExpansions(unittest.TestCase):
def test_double_reference(self):
self.d.setVar("BAR", "bar value")
self.d.setVar("FOO", "${BAR} foo ${BAR}")
val = self.d.getVar("FOO")
val = self.d.getVar("FOO", True)
self.assertEqual(str(val), "bar value foo bar value")
def test_direct_recursion(self):
@@ -129,12 +129,12 @@ class DataExpansions(unittest.TestCase):
def test_incomplete_varexp_single_quotes(self):
self.d.setVar("FOO", "sed -i -e 's:IP{:I${:g' $pc")
val = self.d.getVar("FOO")
val = self.d.getVar("FOO", True)
self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc")
def test_nonstring(self):
self.d.setVar("TEST", 5)
val = self.d.getVar("TEST")
val = self.d.getVar("TEST", True)
self.assertEqual(str(val), "5")
def test_rename(self):
@@ -234,19 +234,19 @@ class TestConcat(unittest.TestCase):
def test_prepend(self):
self.d.setVar("TEST", "${VAL}")
self.d.prependVar("TEST", "${FOO}:")
self.assertEqual(self.d.getVar("TEST"), "foo:val")
self.assertEqual(self.d.getVar("TEST", True), "foo:val")
def test_append(self):
self.d.setVar("TEST", "${VAL}")
self.d.appendVar("TEST", ":${BAR}")
self.assertEqual(self.d.getVar("TEST"), "val:bar")
self.assertEqual(self.d.getVar("TEST", True), "val:bar")
def test_multiple_append(self):
self.d.setVar("TEST", "${VAL}")
self.d.prependVar("TEST", "${FOO}:")
self.d.appendVar("TEST", ":val2")
self.d.appendVar("TEST", ":${BAR}")
self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar")
self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
class TestConcatOverride(unittest.TestCase):
def setUp(self):
@@ -258,66 +258,62 @@ class TestConcatOverride(unittest.TestCase):
def test_prepend(self):
self.d.setVar("TEST", "${VAL}")
self.d.setVar("TEST_prepend", "${FOO}:")
self.assertEqual(self.d.getVar("TEST"), "foo:val")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "foo:val")
def test_append(self):
self.d.setVar("TEST", "${VAL}")
self.d.setVar("TEST_append", ":${BAR}")
self.assertEqual(self.d.getVar("TEST"), "val:bar")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "val:bar")
def test_multiple_append(self):
self.d.setVar("TEST", "${VAL}")
self.d.setVar("TEST_prepend", "${FOO}:")
self.d.setVar("TEST_append", ":val2")
self.d.setVar("TEST_append", ":${BAR}")
self.assertEqual(self.d.getVar("TEST"), "foo:val:val2:bar")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
def test_append_unset(self):
self.d.setVar("TEST_prepend", "${FOO}:")
self.d.setVar("TEST_append", ":val2")
self.d.setVar("TEST_append", ":${BAR}")
self.assertEqual(self.d.getVar("TEST"), "foo::val2:bar")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "foo::val2:bar")
def test_remove(self):
self.d.setVar("TEST", "${VAL} ${BAR}")
self.d.setVar("TEST_remove", "val")
self.assertEqual(self.d.getVar("TEST"), "bar")
def test_remove_cleared(self):
self.d.setVar("TEST", "${VAL} ${BAR}")
self.d.setVar("TEST_remove", "val")
self.d.setVar("TEST", "${VAL} ${BAR}")
self.assertEqual(self.d.getVar("TEST"), "val bar")
# Ensure the value is unchanged if we have an inactive remove override
# (including that whitespace is preserved)
def test_remove_inactive_override(self):
self.d.setVar("TEST", "${VAL} ${BAR} 123")
self.d.setVar("TEST_remove_inactiveoverride", "val")
self.assertEqual(self.d.getVar("TEST"), "val bar 123")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "bar")
def test_doubleref_remove(self):
self.d.setVar("TEST", "${VAL} ${BAR}")
self.d.setVar("TEST_remove", "val")
self.d.setVar("TEST_TEST", "${TEST} ${TEST}")
self.assertEqual(self.d.getVar("TEST_TEST"), "bar bar")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST_TEST", True), "bar bar")
def test_empty_remove(self):
self.d.setVar("TEST", "")
self.d.setVar("TEST_remove", "val")
self.assertEqual(self.d.getVar("TEST"), "")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "")
def test_remove_expansion(self):
self.d.setVar("BAR", "Z")
self.d.setVar("TEST", "${BAR}/X Y")
self.d.setVar("TEST_remove", "${BAR}/X")
self.assertEqual(self.d.getVar("TEST"), "Y")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "Y")
def test_remove_expansion_items(self):
self.d.setVar("TEST", "A B C D")
self.d.setVar("BAR", "B D")
self.d.setVar("TEST_remove", "${BAR}")
self.assertEqual(self.d.getVar("TEST"), "A C")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "A C")
class TestOverrides(unittest.TestCase):
def setUp(self):
@@ -326,53 +322,60 @@ class TestOverrides(unittest.TestCase):
self.d.setVar("TEST", "testvalue")
def test_no_override(self):
self.assertEqual(self.d.getVar("TEST"), "testvalue")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "testvalue")
def test_one_override(self):
self.d.setVar("TEST_bar", "testvalue2")
self.assertEqual(self.d.getVar("TEST"), "testvalue2")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "testvalue2")
def test_one_override_unset(self):
self.d.setVar("TEST2_bar", "testvalue2")
self.assertEqual(self.d.getVar("TEST2"), "testvalue2")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST2", True), "testvalue2")
self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST2', 'OVERRIDES', 'TEST2_bar'])
def test_multiple_override(self):
self.d.setVar("TEST_bar", "testvalue2")
self.d.setVar("TEST_local", "testvalue3")
self.d.setVar("TEST_foo", "testvalue4")
self.assertEqual(self.d.getVar("TEST"), "testvalue3")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
self.assertCountEqual(list(self.d.keys()), ['TEST', 'TEST_foo', 'OVERRIDES', 'TEST_bar', 'TEST_local'])
def test_multiple_combined_overrides(self):
self.d.setVar("TEST_local_foo_bar", "testvalue3")
self.assertEqual(self.d.getVar("TEST"), "testvalue3")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
def test_multiple_overrides_unset(self):
self.d.setVar("TEST2_local_foo_bar", "testvalue3")
self.assertEqual(self.d.getVar("TEST2"), "testvalue3")
bb.data.update_data(self.d)
self.assertEqual(self.d.getVar("TEST2", True), "testvalue3")
def test_keyexpansion_override(self):
self.d.setVar("LOCAL", "local")
self.d.setVar("TEST_bar", "testvalue2")
self.d.setVar("TEST_${LOCAL}", "testvalue3")
self.d.setVar("TEST_foo", "testvalue4")
bb.data.update_data(self.d)
bb.data.expandKeys(self.d)
self.assertEqual(self.d.getVar("TEST"), "testvalue3")
self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
def test_rename_override(self):
self.d.setVar("ALTERNATIVE_ncurses-tools_class-target", "a")
self.d.setVar("OVERRIDES", "class-target")
bb.data.update_data(self.d)
self.d.renameVar("ALTERNATIVE_ncurses-tools", "ALTERNATIVE_lib32-ncurses-tools")
self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools"), "a")
self.assertEqual(self.d.getVar("ALTERNATIVE_lib32-ncurses-tools", True), "a")
def test_underscore_override(self):
self.d.setVar("TEST_bar", "testvalue2")
self.d.setVar("TEST_some_val", "testvalue3")
self.d.setVar("TEST_foo", "testvalue4")
self.d.setVar("OVERRIDES", "foo:bar:some_val")
self.assertEqual(self.d.getVar("TEST"), "testvalue3")
self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
class TestKeyExpansion(unittest.TestCase):
def setUp(self):
@@ -386,7 +389,7 @@ class TestKeyExpansion(unittest.TestCase):
with LogRecord() as logs:
bb.data.expandKeys(self.d)
self.assertTrue(logContains("Variable key VAL_${FOO} (A) replaces original key VAL_foo (B)", logs))
self.assertEqual(self.d.getVar("VAL_foo"), "A")
self.assertEqual(self.d.getVar("VAL_foo", True), "A")
class TestFlags(unittest.TestCase):
def setUp(self):
@@ -441,167 +444,3 @@ class Contains(unittest.TestCase):
self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x", True, False, self.d))
self.assertFalse(bb.utils.contains_any("SOMEFLAG", "x y z", True, False, self.d))
class Serialize(unittest.TestCase):
def test_serialize(self):
import tempfile
import pickle
d = bb.data.init()
d.enableTracking()
d.setVar('HELLO', 'world')
d.setVarFlag('HELLO', 'other', 'planet')
with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
tmpfilename = tmpfile.name
pickle.dump(d, tmpfile)
with open(tmpfilename, 'rb') as f:
newd = pickle.load(f)
os.remove(tmpfilename)
self.assertEqual(d, newd)
self.assertEqual(newd.getVar('HELLO'), 'world')
self.assertEqual(newd.getVarFlag('HELLO', 'other'), 'planet')
# Remote datastore tests
# These really only test the interface, since in actual usage we have a
# tinfoil connector that does everything over RPC, and this doesn't test
# that.
class TestConnector:
d = None
def __init__(self, d):
self.d = d
def getVar(self, name):
return self.d._findVar(name)
def getKeys(self):
return set(self.d.keys())
def getVarHistory(self, name):
return self.d.varhistory.variable(name)
def expandPythonRef(self, varname, expr, d):
localdata = self.d.createCopy()
for key in d.localkeys():
localdata.setVar(d.getVar(key))
varparse = bb.data_smart.VariableParse(varname, localdata)
return varparse.python_sub(expr)
def setVar(self, name, value):
self.d.setVar(name, value)
def setVarFlag(self, name, flag, value):
self.d.setVarFlag(name, flag, value)
def delVar(self, name):
self.d.delVar(name)
return False
def delVarFlag(self, name, flag):
self.d.delVarFlag(name, flag)
return False
def renameVar(self, name, newname):
self.d.renameVar(name, newname)
return False
class Remote(unittest.TestCase):
def test_remote(self):
d1 = bb.data.init()
d1.enableTracking()
d2 = bb.data.init()
d2.enableTracking()
connector = TestConnector(d1)
d2.setVar('_remote_data', connector)
d1.setVar('HELLO', 'world')
d1.setVarFlag('OTHER', 'flagname', 'flagvalue')
self.assertEqual(d2.getVar('HELLO'), 'world')
self.assertEqual(d2.expand('${HELLO}'), 'world')
self.assertEqual(d2.expand('${@d.getVar("HELLO")}'), 'world')
self.assertIn('flagname', d2.getVarFlags('OTHER'))
self.assertEqual(d2.getVarFlag('OTHER', 'flagname'), 'flagvalue')
self.assertEqual(d1.varhistory.variable('HELLO'), d2.varhistory.variable('HELLO'))
# Test setVar on client side affects server
d2.setVar('HELLO', 'other-world')
self.assertEqual(d1.getVar('HELLO'), 'other-world')
# Test setVarFlag on client side affects server
d2.setVarFlag('HELLO', 'flagname', 'flagvalue')
self.assertEqual(d1.getVarFlag('HELLO', 'flagname'), 'flagvalue')
# Test client side data is incorporated in python expansion (which is done on server)
d2.setVar('FOO', 'bar')
self.assertEqual(d2.expand('${@d.getVar("FOO")}'), 'bar')
# Test overrides work
d1.setVar('FOO_test', 'baz')
d1.appendVar('OVERRIDES', ':test')
self.assertEqual(d2.getVar('FOO'), 'baz')
# Remote equivalents of local test classes
# Note that these aren't perfect since we only test in one direction
class RemoteDataExpansions(DataExpansions):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1["foo"] = "value_of_foo"
self.d1["bar"] = "value_of_bar"
self.d1["value_of_foo"] = "value_of_'value_of_foo'"
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteNestedExpansions(TestNestedExpansions):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1["foo"] = "foo"
self.d1["bar"] = "bar"
self.d1["value_of_foobar"] = "187"
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteConcat(TestConcat):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1.setVar("FOO", "foo")
self.d1.setVar("VAL", "val")
self.d1.setVar("BAR", "bar")
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteConcatOverride(TestConcatOverride):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1.setVar("FOO", "foo")
self.d1.setVar("VAL", "val")
self.d1.setVar("BAR", "bar")
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteOverrides(TestOverrides):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1.setVar("OVERRIDES", "foo:bar:local")
self.d1.setVar("TEST", "testvalue")
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteKeyExpansion(TestKeyExpansion):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1.setVar("FOO", "foo")
self.d1.setVar("BAR", "foo")
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)
class TestRemoteFlags(TestFlags):
def setUp(self):
self.d1 = bb.data.init()
self.d = bb.data.init()
self.d1.setVar("foo", "value of foo")
self.d1.setVarFlag("foo", "flag1", "value of flag1")
self.d1.setVarFlag("foo", "flag2", "value of flag2")
connector = TestConnector(self.d1)
self.d.setVar('_remote_data', connector)

View File

@@ -1,986 +0,0 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# BitBake Tests for the Event implementation (event.py)
#
# Copyright (C) 2017 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
import unittest
import bb
import logging
import bb.compat
import bb.event
import importlib
import threading
import time
import pickle
from unittest.mock import Mock
from unittest.mock import call
from bb.msg import BBLogFormatter
class EventQueueStubBase(object):
""" Base class for EventQueueStub classes """
def __init__(self):
self.event_calls = []
return
def _store_event_data_string(self, event):
if isinstance(event, logging.LogRecord):
formatter = BBLogFormatter("%(levelname)s: %(message)s")
self.event_calls.append(formatter.format(event))
else:
self.event_calls.append(bb.event.getName(event))
return
class EventQueueStub(EventQueueStubBase):
""" Class used as specification for UI event handler queue stub objects """
def __init__(self):
super(EventQueueStub, self).__init__()
def send(self, event):
super(EventQueueStub, self)._store_event_data_string(event)
class PickleEventQueueStub(EventQueueStubBase):
""" Class used as specification for UI event handler queue stub objects
with sendpickle method """
def __init__(self):
super(PickleEventQueueStub, self).__init__()
def sendpickle(self, pickled_event):
event = pickle.loads(pickled_event)
super(PickleEventQueueStub, self)._store_event_data_string(event)
class UIClientStub(object):
""" Class used as specification for UI event handler stub objects """
def __init__(self):
self.event = None
class EventHandlingTest(unittest.TestCase):
""" Event handling test class """
def setUp(self):
self._test_process = Mock()
ui_client1 = UIClientStub()
ui_client2 = UIClientStub()
self._test_ui1 = Mock(wraps=ui_client1)
self._test_ui2 = Mock(wraps=ui_client2)
importlib.reload(bb.event)
def _create_test_handlers(self):
""" Method used to create a test handler ordered dictionary """
test_handlers = bb.compat.OrderedDict()
test_handlers["handler1"] = self._test_process.handler1
test_handlers["handler2"] = self._test_process.handler2
return test_handlers
def test_class_handlers(self):
""" Test set_class_handlers and get_class_handlers methods """
test_handlers = self._create_test_handlers()
bb.event.set_class_handlers(test_handlers)
self.assertEqual(test_handlers,
bb.event.get_class_handlers())
def test_handlers(self):
""" Test set_handlers and get_handlers """
test_handlers = self._create_test_handlers()
bb.event.set_handlers(test_handlers)
self.assertEqual(test_handlers,
bb.event.get_handlers())
def test_clean_class_handlers(self):
""" Test clean_class_handlers method """
cleanDict = bb.compat.OrderedDict()
self.assertEqual(cleanDict,
bb.event.clean_class_handlers())
def test_register(self):
""" Test register method for class handlers """
result = bb.event.register("handler", self._test_process.handler)
self.assertEqual(result, bb.event.Registered)
handlers_dict = bb.event.get_class_handlers()
self.assertIn("handler", handlers_dict)
def test_already_registered(self):
""" Test detection of an already registed class handler """
bb.event.register("handler", self._test_process.handler)
handlers_dict = bb.event.get_class_handlers()
self.assertIn("handler", handlers_dict)
result = bb.event.register("handler", self._test_process.handler)
self.assertEqual(result, bb.event.AlreadyRegistered)
def test_register_from_string(self):
""" Test register method receiving code in string """
result = bb.event.register("string_handler", " return True")
self.assertEqual(result, bb.event.Registered)
handlers_dict = bb.event.get_class_handlers()
self.assertIn("string_handler", handlers_dict)
def test_register_with_mask(self):
""" Test register method with event masking """
mask = ["bb.event.OperationStarted",
"bb.event.OperationCompleted"]
result = bb.event.register("event_handler",
self._test_process.event_handler,
mask)
self.assertEqual(result, bb.event.Registered)
handlers_dict = bb.event.get_class_handlers()
self.assertIn("event_handler", handlers_dict)
def test_remove(self):
""" Test remove method for class handlers """
test_handlers = self._create_test_handlers()
bb.event.set_class_handlers(test_handlers)
count = len(test_handlers)
bb.event.remove("handler1", None)
test_handlers = bb.event.get_class_handlers()
self.assertEqual(len(test_handlers), count - 1)
with self.assertRaises(KeyError):
bb.event.remove("handler1", None)
def test_execute_handler(self):
""" Test execute_handler method for class handlers """
mask = ["bb.event.OperationProgress"]
result = bb.event.register("event_handler",
self._test_process.event_handler,
mask)
self.assertEqual(result, bb.event.Registered)
event = bb.event.OperationProgress(current=10, total=100)
bb.event.execute_handler("event_handler",
self._test_process.event_handler,
event,
None)
self._test_process.event_handler.assert_called_once_with(event)
def test_fire_class_handlers(self):
""" Test fire_class_handlers method """
mask = ["bb.event.OperationStarted"]
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
mask)
self.assertEqual(result, bb.event.Registered)
result = bb.event.register("event_handler2",
self._test_process.event_handler2,
"*")
self.assertEqual(result, bb.event.Registered)
event1 = bb.event.OperationStarted()
event2 = bb.event.OperationCompleted(total=123)
bb.event.fire_class_handlers(event1, None)
bb.event.fire_class_handlers(event2, None)
bb.event.fire_class_handlers(event2, None)
expected_event_handler1 = [call(event1)]
expected_event_handler2 = [call(event1),
call(event2),
call(event2)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected_event_handler1)
self.assertEqual(self._test_process.event_handler2.call_args_list,
expected_event_handler2)
def test_class_handler_filters(self):
""" Test filters for class handlers """
mask = ["bb.event.OperationStarted"]
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
mask)
self.assertEqual(result, bb.event.Registered)
result = bb.event.register("event_handler2",
self._test_process.event_handler2,
"*")
self.assertEqual(result, bb.event.Registered)
bb.event.set_eventfilter(
lambda name, handler, event, d :
name == 'event_handler2' and
bb.event.getName(event) == "OperationStarted")
event1 = bb.event.OperationStarted()
event2 = bb.event.OperationCompleted(total=123)
bb.event.fire_class_handlers(event1, None)
bb.event.fire_class_handlers(event2, None)
bb.event.fire_class_handlers(event2, None)
expected_event_handler1 = []
expected_event_handler2 = [call(event1)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected_event_handler1)
self.assertEqual(self._test_process.event_handler2.call_args_list,
expected_event_handler2)
def test_change_handler_event_mapping(self):
""" Test changing the event mapping for class handlers """
event1 = bb.event.OperationStarted()
event2 = bb.event.OperationCompleted(total=123)
# register handler for all events
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
"*")
self.assertEqual(result, bb.event.Registered)
bb.event.fire_class_handlers(event1, None)
bb.event.fire_class_handlers(event2, None)
expected = [call(event1), call(event2)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected)
# unregister handler and register it only for OperationStarted
bb.event.remove("event_handler1",
self._test_process.event_handler1)
mask = ["bb.event.OperationStarted"]
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
mask)
self.assertEqual(result, bb.event.Registered)
bb.event.fire_class_handlers(event1, None)
bb.event.fire_class_handlers(event2, None)
expected = [call(event1), call(event2), call(event1)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected)
# unregister handler and register it only for OperationCompleted
bb.event.remove("event_handler1",
self._test_process.event_handler1)
mask = ["bb.event.OperationCompleted"]
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
mask)
self.assertEqual(result, bb.event.Registered)
bb.event.fire_class_handlers(event1, None)
bb.event.fire_class_handlers(event2, None)
expected = [call(event1), call(event2), call(event1), call(event2)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected)
def test_register_UIHhandler(self):
""" Test register_UIHhandler method """
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
def test_UIHhandler_already_registered(self):
""" Test registering an UIHhandler already existing """
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 2)
def test_unregister_UIHhandler(self):
""" Test unregister_UIHhandler method """
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
result = bb.event.unregister_UIHhandler(1)
self.assertIs(result, None)
def test_fire_ui_handlers(self):
""" Test fire_ui_handlers method """
self._test_ui1.event = Mock(spec_set=EventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
self._test_ui2.event = Mock(spec_set=PickleEventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
self.assertEqual(result, 2)
event1 = bb.event.OperationStarted()
bb.event.fire_ui_handlers(event1, None)
expected = [call(event1)]
self.assertEqual(self._test_ui1.event.send.call_args_list,
expected)
expected = [call(pickle.dumps(event1))]
self.assertEqual(self._test_ui2.event.sendpickle.call_args_list,
expected)
def test_ui_handler_mask_filter(self):
""" Test filters for UI handlers """
mask = ["bb.event.OperationStarted"]
debug_domains = {}
self._test_ui1.event = Mock(spec_set=EventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
bb.event.set_UIHmask(result, logging.INFO, debug_domains, mask)
self._test_ui2.event = Mock(spec_set=PickleEventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
bb.event.set_UIHmask(result, logging.INFO, debug_domains, mask)
event1 = bb.event.OperationStarted()
event2 = bb.event.OperationCompleted(total=1)
bb.event.fire_ui_handlers(event1, None)
bb.event.fire_ui_handlers(event2, None)
expected = [call(event1)]
self.assertEqual(self._test_ui1.event.send.call_args_list,
expected)
expected = [call(pickle.dumps(event1))]
self.assertEqual(self._test_ui2.event.sendpickle.call_args_list,
expected)
def test_ui_handler_log_filter(self):
""" Test log filters for UI handlers """
mask = ["*"]
debug_domains = {'BitBake.Foo': logging.WARNING}
self._test_ui1.event = EventQueueStub()
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
bb.event.set_UIHmask(result, logging.ERROR, debug_domains, mask)
self._test_ui2.event = PickleEventQueueStub()
result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
bb.event.set_UIHmask(result, logging.ERROR, debug_domains, mask)
event1 = bb.event.OperationStarted()
bb.event.fire_ui_handlers(event1, None) # All events match
event_log_handler = bb.event.LogHandler()
logger = logging.getLogger("BitBake")
logger.addHandler(event_log_handler)
logger1 = logging.getLogger("BitBake.Foo")
logger1.warning("Test warning LogRecord1") # Matches debug_domains level
logger1.info("Test info LogRecord") # Filtered out
logger2 = logging.getLogger("BitBake.Bar")
logger2.error("Test error LogRecord") # Matches filter base level
logger2.warning("Test warning LogRecord2") # Filtered out
logger.removeHandler(event_log_handler)
expected = ['OperationStarted',
'WARNING: Test warning LogRecord1',
'ERROR: Test error LogRecord']
self.assertEqual(self._test_ui1.event.event_calls, expected)
self.assertEqual(self._test_ui2.event.event_calls, expected)
def test_fire(self):
""" Test fire method used to trigger class and ui event handlers """
mask = ["bb.event.ConfigParsed"]
result = bb.event.register("event_handler1",
self._test_process.event_handler1,
mask)
self._test_ui1.event = Mock(spec_set=EventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
event1 = bb.event.ConfigParsed()
bb.event.fire(event1, None)
expected = [call(event1)]
self.assertEqual(self._test_process.event_handler1.call_args_list,
expected)
self.assertEqual(self._test_ui1.event.send.call_args_list,
expected)
def test_fire_from_worker(self):
""" Test fire_from_worker method """
self._test_ui1.event = Mock(spec_set=EventQueueStub)
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
event1 = bb.event.ConfigParsed()
bb.event.fire_from_worker(event1, None)
expected = [call(event1)]
self.assertEqual(self._test_ui1.event.send.call_args_list,
expected)
def test_worker_fire(self):
""" Test the triggering of bb.event.worker_fire callback """
bb.event.worker_fire = Mock()
event = bb.event.Event()
bb.event.fire(event, None)
expected = [call(event, None)]
self.assertEqual(bb.event.worker_fire.call_args_list, expected)
def test_print_ui_queue(self):
""" Test print_ui_queue method """
event1 = bb.event.OperationStarted()
event2 = bb.event.OperationCompleted(total=123)
bb.event.fire(event1, None)
bb.event.fire(event2, None)
event_log_handler = bb.event.LogHandler()
logger = logging.getLogger("BitBake")
logger.addHandler(event_log_handler)
logger.info("Test info LogRecord")
logger.warning("Test warning LogRecord")
with self.assertLogs("BitBake", level="INFO") as cm:
bb.event.print_ui_queue()
logger.removeHandler(event_log_handler)
self.assertEqual(cm.output,
["INFO:BitBake:Test info LogRecord",
"WARNING:BitBake:Test warning LogRecord"])
def _set_threadlock_test_mockups(self):
""" Create UI event handler mockups used in enable and disable
threadlock tests """
def ui1_event_send(event):
if type(event) is bb.event.ConfigParsed:
self._threadlock_test_calls.append("w1_ui1")
if type(event) is bb.event.OperationStarted:
self._threadlock_test_calls.append("w2_ui1")
time.sleep(2)
def ui2_event_send(event):
if type(event) is bb.event.ConfigParsed:
self._threadlock_test_calls.append("w1_ui2")
if type(event) is bb.event.OperationStarted:
self._threadlock_test_calls.append("w2_ui2")
time.sleep(2)
self._threadlock_test_calls = []
self._test_ui1.event = EventQueueStub()
self._test_ui1.event.send = ui1_event_send
result = bb.event.register_UIHhandler(self._test_ui1, mainui=True)
self.assertEqual(result, 1)
self._test_ui2.event = EventQueueStub()
self._test_ui2.event.send = ui2_event_send
result = bb.event.register_UIHhandler(self._test_ui2, mainui=True)
self.assertEqual(result, 2)
def _set_and_run_threadlock_test_workers(self):
""" Create and run the workers used to trigger events in enable and
disable threadlock tests """
worker1 = threading.Thread(target=self._thread_lock_test_worker1)
worker2 = threading.Thread(target=self._thread_lock_test_worker2)
worker1.start()
time.sleep(1)
worker2.start()
worker1.join()
worker2.join()
def _thread_lock_test_worker1(self):
""" First worker used to fire the ConfigParsed event for enable and
disable threadlocks tests """
bb.event.fire(bb.event.ConfigParsed(), None)
def _thread_lock_test_worker2(self):
""" Second worker used to fire the OperationStarted event for enable
and disable threadlocks tests """
bb.event.fire(bb.event.OperationStarted(), None)
def test_enable_threadlock(self):
""" Test enable_threadlock method """
self._set_threadlock_test_mockups()
bb.event.enable_threadlock()
self._set_and_run_threadlock_test_workers()
# Calls to UI handlers should be in order as all the registered
# handlers for the event coming from the first worker should be
# called before processing the event from the second worker.
self.assertEqual(self._threadlock_test_calls,
["w1_ui1", "w1_ui2", "w2_ui1", "w2_ui2"])
def test_disable_threadlock(self):
""" Test disable_threadlock method """
self._set_threadlock_test_mockups()
bb.event.disable_threadlock()
self._set_and_run_threadlock_test_workers()
# Calls to UI handlers should be intertwined together. Thanks to the
# delay in the registered handlers for the event coming from the first
# worker, the event coming from the second worker starts being
# processed before finishing handling the first worker event.
self.assertEqual(self._threadlock_test_calls,
["w1_ui1", "w2_ui1", "w1_ui2", "w2_ui2"])
class EventClassesTest(unittest.TestCase):
""" Event classes test class """
_worker_pid = 54321
def setUp(self):
bb.event.worker_pid = EventClassesTest._worker_pid
def test_Event(self):
""" Test the Event base class """
event = bb.event.Event()
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_HeartbeatEvent(self):
""" Test the HeartbeatEvent class """
time = 10
event = bb.event.HeartbeatEvent(time)
self.assertEqual(event.time, time)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_OperationStarted(self):
""" Test OperationStarted event class """
msg = "Foo Bar"
event = bb.event.OperationStarted(msg)
self.assertEqual(event.msg, msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_OperationCompleted(self):
""" Test OperationCompleted event class """
msg = "Foo Bar"
total = 123
event = bb.event.OperationCompleted(total, msg)
self.assertEqual(event.msg, msg)
self.assertEqual(event.total, total)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_OperationProgress(self):
""" Test OperationProgress event class """
msg = "Foo Bar"
total = 123
current = 111
event = bb.event.OperationProgress(current, total, msg)
self.assertEqual(event.msg, msg + ": %s/%s" % (current, total))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ConfigParsed(self):
""" Test the ConfigParsed class """
event = bb.event.ConfigParsed()
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_MultiConfigParsed(self):
""" Test MultiConfigParsed event class """
mcdata = {"foobar": "Foo Bar"}
event = bb.event.MultiConfigParsed(mcdata)
self.assertEqual(event.mcdata, mcdata)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_RecipeEvent(self):
""" Test RecipeEvent event base class """
callback = lambda a: 2 * a
event = bb.event.RecipeEvent(callback)
self.assertEqual(event.fn(1), callback(1))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_RecipePreFinalise(self):
""" Test RecipePreFinalise event class """
callback = lambda a: 2 * a
event = bb.event.RecipePreFinalise(callback)
self.assertEqual(event.fn(1), callback(1))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_RecipeTaskPreProcess(self):
""" Test RecipeTaskPreProcess event class """
callback = lambda a: 2 * a
tasklist = [("foobar", callback)]
event = bb.event.RecipeTaskPreProcess(callback, tasklist)
self.assertEqual(event.fn(1), callback(1))
self.assertEqual(event.tasklist, tasklist)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_RecipeParsed(self):
""" Test RecipeParsed event base class """
callback = lambda a: 2 * a
event = bb.event.RecipeParsed(callback)
self.assertEqual(event.fn(1), callback(1))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_StampUpdate(self):
targets = ["foo", "bar"]
stampfns = [lambda:"foobar"]
event = bb.event.StampUpdate(targets, stampfns)
self.assertEqual(event.targets, targets)
self.assertEqual(event.stampPrefix, stampfns)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_BuildBase(self):
""" Test base class for bitbake build events """
name = "foo"
pkgs = ["bar"]
failures = 123
event = bb.event.BuildBase(name, pkgs, failures)
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), failures)
name = event.name = "bar"
pkgs = event.pkgs = ["foo"]
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), failures)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_BuildInit(self):
""" Test class for bitbake build invocation events """
event = bb.event.BuildInit()
self.assertEqual(event.name, None)
self.assertEqual(event.pkgs, [])
self.assertEqual(event.getFailures(), 0)
name = event.name = "bar"
pkgs = event.pkgs = ["foo"]
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), 0)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_BuildStarted(self):
""" Test class for build started events """
name = "foo"
pkgs = ["bar"]
failures = 123
event = bb.event.BuildStarted(name, pkgs, failures)
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), failures)
self.assertEqual(event.msg, "Building Started")
name = event.name = "bar"
pkgs = event.pkgs = ["foo"]
msg = event.msg = "foobar"
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), failures)
self.assertEqual(event.msg, msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_BuildCompleted(self):
""" Test class for build completed events """
total = 1000
name = "foo"
pkgs = ["bar"]
failures = 123
interrupted = 1
event = bb.event.BuildCompleted(total, name, pkgs, failures,
interrupted)
self.assertEqual(event.name, name)
self.assertEqual(event.pkgs, pkgs)
self.assertEqual(event.getFailures(), failures)
self.assertEqual(event.msg, "Building Failed")
event2 = bb.event.BuildCompleted(total, name, pkgs)
self.assertEqual(event2.name, name)
self.assertEqual(event2.pkgs, pkgs)
self.assertEqual(event2.getFailures(), 0)
self.assertEqual(event2.msg, "Building Succeeded")
self.assertEqual(event2.pid, EventClassesTest._worker_pid)
def test_DiskFull(self):
""" Test DiskFull event class """
dev = "/dev/foo"
type = "ext4"
freespace = "104M"
mountpoint = "/"
event = bb.event.DiskFull(dev, type, freespace, mountpoint)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_MonitorDiskEvent(self):
""" Test MonitorDiskEvent class """
available_bytes = 10000000
free_bytes = 90000000
total_bytes = 1000000000
du = bb.event.DiskUsageSample(available_bytes, free_bytes,
total_bytes)
event = bb.event.MonitorDiskEvent(du)
self.assertEqual(event.disk_usage.available_bytes, available_bytes)
self.assertEqual(event.disk_usage.free_bytes, free_bytes)
self.assertEqual(event.disk_usage.total_bytes, total_bytes)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_NoProvider(self):
""" Test NoProvider event class """
item = "foobar"
event1 = bb.event.NoProvider(item)
self.assertEqual(event1.getItem(), item)
self.assertEqual(event1.isRuntime(), False)
self.assertEqual(str(event1), "Nothing PROVIDES 'foobar'")
runtime = True
dependees = ["foo", "bar"]
reasons = None
close_matches = ["foibar", "footbar"]
event2 = bb.event.NoProvider(item, runtime, dependees, reasons,
close_matches)
self.assertEqual(event2.isRuntime(), True)
expected = ("Nothing RPROVIDES 'foobar' (but foo, bar RDEPENDS"
" on or otherwise requires it). Close matches:\n"
" foibar\n"
" footbar")
self.assertEqual(str(event2), expected)
reasons = ["Item does not exist on database"]
close_matches = ["foibar", "footbar"]
event3 = bb.event.NoProvider(item, runtime, dependees, reasons,
close_matches)
expected = ("Nothing RPROVIDES 'foobar' (but foo, bar RDEPENDS"
" on or otherwise requires it)\n"
"Item does not exist on database")
self.assertEqual(str(event3), expected)
self.assertEqual(event3.pid, EventClassesTest._worker_pid)
def test_MultipleProviders(self):
""" Test MultipleProviders event class """
item = "foobar"
candidates = ["foobarv1", "foobars"]
event1 = bb.event.MultipleProviders(item, candidates)
self.assertEqual(event1.isRuntime(), False)
self.assertEqual(event1.getItem(), item)
self.assertEqual(event1.getCandidates(), candidates)
expected = ("Multiple providers are available for foobar (foobarv1,"
" foobars)\n"
"Consider defining a PREFERRED_PROVIDER entry to match "
"foobar")
self.assertEqual(str(event1), expected)
runtime = True
event2 = bb.event.MultipleProviders(item, candidates, runtime)
self.assertEqual(event2.isRuntime(), runtime)
expected = ("Multiple providers are available for runtime foobar "
"(foobarv1, foobars)\n"
"Consider defining a PREFERRED_RPROVIDER entry to match "
"foobar")
self.assertEqual(str(event2), expected)
self.assertEqual(event2.pid, EventClassesTest._worker_pid)
def test_ParseStarted(self):
""" Test ParseStarted event class """
total = 123
event = bb.event.ParseStarted(total)
self.assertEqual(event.msg, "Recipe parsing Started")
self.assertEqual(event.total, total)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ParseCompleted(self):
""" Test ParseCompleted event class """
cached = 10
parsed = 13
skipped = 7
virtuals = 2
masked = 1
errors = 0
total = 23
event = bb.event.ParseCompleted(cached, parsed, skipped, masked,
virtuals, errors, total)
self.assertEqual(event.msg, "Recipe parsing Completed")
expected = [cached, parsed, skipped, virtuals, masked, errors,
cached + parsed, total]
actual = [event.cached, event.parsed, event.skipped, event.virtuals,
event.masked, event.errors, event.sofar, event.total]
self.assertEqual(str(actual), str(expected))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ParseProgress(self):
""" Test ParseProgress event class """
current = 10
total = 100
event = bb.event.ParseProgress(current, total)
self.assertEqual(event.msg,
"Recipe parsing" + ": %s/%s" % (current, total))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_CacheLoadStarted(self):
""" Test CacheLoadStarted event class """
total = 123
event = bb.event.CacheLoadStarted(total)
self.assertEqual(event.msg, "Loading cache Started")
self.assertEqual(event.total, total)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_CacheLoadProgress(self):
""" Test CacheLoadProgress event class """
current = 10
total = 100
event = bb.event.CacheLoadProgress(current, total)
self.assertEqual(event.msg,
"Loading cache" + ": %s/%s" % (current, total))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_CacheLoadCompleted(self):
""" Test CacheLoadCompleted event class """
total = 23
num_entries = 12
event = bb.event.CacheLoadCompleted(total, num_entries)
self.assertEqual(event.msg, "Loading cache Completed")
expected = [total, num_entries]
actual = [event.total, event.num_entries]
self.assertEqual(str(actual), str(expected))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_TreeDataPreparationStarted(self):
""" Test TreeDataPreparationStarted event class """
event = bb.event.TreeDataPreparationStarted()
self.assertEqual(event.msg, "Preparing tree data Started")
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_TreeDataPreparationProgress(self):
""" Test TreeDataPreparationProgress event class """
current = 10
total = 100
event = bb.event.TreeDataPreparationProgress(current, total)
self.assertEqual(event.msg,
"Preparing tree data" + ": %s/%s" % (current, total))
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_TreeDataPreparationCompleted(self):
""" Test TreeDataPreparationCompleted event class """
total = 23
event = bb.event.TreeDataPreparationCompleted(total)
self.assertEqual(event.msg, "Preparing tree data Completed")
self.assertEqual(event.total, total)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_DepTreeGenerated(self):
""" Test DepTreeGenerated event class """
depgraph = Mock()
event = bb.event.DepTreeGenerated(depgraph)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_TargetsTreeGenerated(self):
""" Test TargetsTreeGenerated event class """
model = Mock()
event = bb.event.TargetsTreeGenerated(model)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ReachableStamps(self):
""" Test ReachableStamps event class """
stamps = [Mock(), Mock()]
event = bb.event.ReachableStamps(stamps)
self.assertEqual(event.stamps, stamps)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_FilesMatchingFound(self):
""" Test FilesMatchingFound event class """
pattern = "foo.*bar"
matches = ["foobar"]
event = bb.event.FilesMatchingFound(pattern, matches)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ConfigFilesFound(self):
""" Test ConfigFilesFound event class """
variable = "FOO_BAR"
values = ["foo", "bar"]
event = bb.event.ConfigFilesFound(variable, values)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ConfigFilePathFound(self):
""" Test ConfigFilePathFound event class """
path = "/foo/bar"
event = bb.event.ConfigFilePathFound(path)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_message_classes(self):
""" Test message event classes """
msg = "foobar foo bar"
event = bb.event.MsgBase(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgDebug(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgNote(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgWarn(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgError(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgFatal(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
event = bb.event.MsgPlain(msg)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_LogExecTTY(self):
""" Test LogExecTTY event class """
msg = "foo bar"
prog = "foo.sh"
sleep_delay = 10
retries = 3
event = bb.event.LogExecTTY(msg, prog, sleep_delay, retries)
self.assertEqual(event.msg, msg)
self.assertEqual(event.prog, prog)
self.assertEqual(event.sleep_delay, sleep_delay)
self.assertEqual(event.retries, retries)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def _throw_zero_division_exception(self):
a = 1 / 0
return
def _worker_handler(self, event, d):
self._returned_event = event
return
def test_LogHandler(self):
""" Test LogHandler class """
logger = logging.getLogger("TestEventClasses")
logger.propagate = False
handler = bb.event.LogHandler(logging.INFO)
logger.addHandler(handler)
bb.event.worker_fire = self._worker_handler
try:
self._throw_zero_division_exception()
except ZeroDivisionError as ex:
logger.exception(ex)
event = self._returned_event
try:
pe = pickle.dumps(event)
newevent = pickle.loads(pe)
except:
self.fail('Logged event is not serializable')
self.assertEqual(event.taskpid, EventClassesTest._worker_pid)
def test_MetadataEvent(self):
""" Test MetadataEvent class """
eventtype = "footype"
eventdata = {"foo": "bar"}
event = bb.event.MetadataEvent(eventtype, eventdata)
self.assertEqual(event.type, eventtype)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ProcessStarted(self):
""" Test ProcessStarted class """
processname = "foo"
total = 9783128974
event = bb.event.ProcessStarted(processname, total)
self.assertEqual(event.processname, processname)
self.assertEqual(event.total, total)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ProcessProgress(self):
""" Test ProcessProgress class """
processname = "foo"
progress = 243224
event = bb.event.ProcessProgress(processname, progress)
self.assertEqual(event.processname, processname)
self.assertEqual(event.progress, progress)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_ProcessFinished(self):
""" Test ProcessFinished class """
processname = "foo"
total = 1242342344
event = bb.event.ProcessFinished(processname)
self.assertEqual(event.processname, processname)
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_SanityCheck(self):
""" Test SanityCheck class """
event1 = bb.event.SanityCheck()
self.assertEqual(event1.generateevents, True)
self.assertEqual(event1.pid, EventClassesTest._worker_pid)
generateevents = False
event2 = bb.event.SanityCheck(generateevents)
self.assertEqual(event2.generateevents, generateevents)
self.assertEqual(event2.pid, EventClassesTest._worker_pid)
def test_SanityCheckPassed(self):
""" Test SanityCheckPassed class """
event = bb.event.SanityCheckPassed()
self.assertEqual(event.pid, EventClassesTest._worker_pid)
def test_SanityCheckFailed(self):
""" Test SanityCheckFailed class """
msg = "The sanity test failed."
event1 = bb.event.SanityCheckFailed(msg)
self.assertEqual(event1.pid, EventClassesTest._worker_pid)
network_error = True
event2 = bb.event.SanityCheckFailed(msg, network_error)
self.assertEqual(event2.pid, EventClassesTest._worker_pid)
def test_network_event_classes(self):
""" Test network event classes """
event1 = bb.event.NetworkTest()
generateevents = False
self.assertEqual(event1.pid, EventClassesTest._worker_pid)
event2 = bb.event.NetworkTest(generateevents)
self.assertEqual(event2.pid, EventClassesTest._worker_pid)
event3 = bb.event.NetworkTestPassed()
self.assertEqual(event3.pid, EventClassesTest._worker_pid)
event4 = bb.event.NetworkTestFailed()
self.assertEqual(event4.pid, EventClassesTest._worker_pid)
def test_FindSigInfoResult(self):
""" Test FindSigInfoResult event class """
result = [Mock()]
event = bb.event.FindSigInfoResult(result)
self.assertEqual(event.result, result)
self.assertEqual(event.pid, EventClassesTest._worker_pid)

File diff suppressed because it is too large Load Diff

View File

@@ -58,9 +58,9 @@ C = "3"
def test_parse_simple(self):
f = self.parsehelper(self.testfile)
d = bb.parse.handle(f.name, self.d)['']
self.assertEqual(d.getVar("A"), "1")
self.assertEqual(d.getVar("B"), "2")
self.assertEqual(d.getVar("C"), "3")
self.assertEqual(d.getVar("A", True), "1")
self.assertEqual(d.getVar("B", True), "2")
self.assertEqual(d.getVar("C", True), "3")
def test_parse_incomplete_function(self):
testfileB = self.testfile.replace("}", "")
@@ -80,31 +80,10 @@ unset B[flag]
def test_parse_unset(self):
f = self.parsehelper(self.unsettest)
d = bb.parse.handle(f.name, self.d)['']
self.assertEqual(d.getVar("A"), None)
self.assertEqual(d.getVarFlag("A","flag"), None)
self.assertEqual(d.getVar("B"), "2")
exporttest = """
A = "a"
export B = "b"
export C
exportD = "d"
"""
def test_parse_exports(self):
f = self.parsehelper(self.exporttest)
d = bb.parse.handle(f.name, self.d)['']
self.assertEqual(d.getVar("A"), "a")
self.assertIsNone(d.getVarFlag("A", "export"))
self.assertEqual(d.getVar("B"), "b")
self.assertEqual(d.getVarFlag("B", "export"), 1)
self.assertIsNone(d.getVar("C"))
self.assertEqual(d.getVarFlag("C", "export"), 1)
self.assertIsNone(d.getVar("D"))
self.assertIsNone(d.getVarFlag("D", "export"))
self.assertEqual(d.getVar("exportD"), "d")
self.assertIsNone(d.getVarFlag("exportD", "export"))
self.assertEqual(d.getVar("A", True), None)
self.assertEqual(d.getVarFlag("A","flag", True), None)
self.assertEqual(d.getVar("B", True), "2")
overridetest = """
RRECOMMENDS_${PN} = "a"
@@ -116,11 +95,11 @@ PN = "gtk+"
def test_parse_overrides(self):
f = self.parsehelper(self.overridetest)
d = bb.parse.handle(f.name, self.d)['']
self.assertEqual(d.getVar("RRECOMMENDS"), "b")
self.assertEqual(d.getVar("RRECOMMENDS", True), "b")
bb.data.expandKeys(d)
self.assertEqual(d.getVar("RRECOMMENDS"), "b")
self.assertEqual(d.getVar("RRECOMMENDS", True), "b")
d.setVar("RRECOMMENDS_gtk+", "c")
self.assertEqual(d.getVar("RRECOMMENDS"), "c")
self.assertEqual(d.getVar("RRECOMMENDS", True), "c")
overridetest2 = """
EXTRA_OECONF = ""
@@ -133,7 +112,7 @@ EXTRA_OECONF_append = " c"
d = bb.parse.handle(f.name, self.d)['']
d.appendVar("EXTRA_OECONF", " d")
d.setVar("OVERRIDES", "class-target")
self.assertEqual(d.getVar("EXTRA_OECONF"), "b c d")
self.assertEqual(d.getVar("EXTRA_OECONF", True), "b c d")
overridetest3 = """
DESCRIPTION = "A"
@@ -145,11 +124,11 @@ PN = "bc"
f = self.parsehelper(self.overridetest3)
d = bb.parse.handle(f.name, self.d)['']
bb.data.expandKeys(d)
self.assertEqual(d.getVar("DESCRIPTION_bc-dev"), "A B")
self.assertEqual(d.getVar("DESCRIPTION_bc-dev", True), "A B")
d.setVar("DESCRIPTION", "E")
d.setVar("DESCRIPTION_bc-dev", "C D")
d.setVar("OVERRIDES", "bc-dev")
self.assertEqual(d.getVar("DESCRIPTION"), "C D")
self.assertEqual(d.getVar("DESCRIPTION", True), "C D")
classextend = """
@@ -180,6 +159,6 @@ python () {
alldata = bb.parse.handle(f.name, self.d)
d1 = alldata['']
d2 = alldata[cls.name]
self.assertEqual(d1.getVar("VAR_var"), "B")
self.assertEqual(d2.getVar("VAR_var"), None)
self.assertEqual(d1.getVar("VAR_var", True), "B")
self.assertEqual(d2.getVar("VAR_var", True), None)

View File

@@ -1,8 +1,7 @@
# tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities
#
# Copyright (C) 2012-2017 Intel Corporation
# Copyright (C) 2012 Intel Corporation
# Copyright (C) 2011 Mentor Graphics Corporation
# Copyright (C) 2006-2012 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -18,319 +17,50 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import logging
import warnings
import os
import sys
import atexit
import re
from collections import OrderedDict, defaultdict
import bb.cache
import bb.cooker
import bb.providers
import bb.taskdata
import bb.utils
import bb.command
import bb.remotedata
from bb.cooker import state, BBCooker, CookerFeatures
from bb.cookerdata import CookerConfiguration, ConfigParameters
from bb.main import setup_bitbake, BitBakeConfigParameters, BBMainException
import bb.fetch2
# We need this in order to shut down the connection to the bitbake server,
# otherwise the process will never properly exit
_server_connections = []
def _terminate_connections():
for connection in _server_connections:
connection.terminate()
atexit.register(_terminate_connections)
class TinfoilUIException(Exception):
"""Exception raised when the UI returns non-zero from its main function"""
def __init__(self, returncode):
self.returncode = returncode
def __repr__(self):
return 'UI module main returned %d' % self.returncode
class TinfoilCommandFailed(Exception):
"""Exception raised when run_command fails"""
class TinfoilDataStoreConnector:
"""Connector object used to enable access to datastore objects via tinfoil"""
def __init__(self, tinfoil, dsindex):
self.tinfoil = tinfoil
self.dsindex = dsindex
def getVar(self, name):
value = self.tinfoil.run_command('dataStoreConnectorFindVar', self.dsindex, name)
overrides = None
if isinstance(value, dict):
if '_connector_origtype' in value:
value['_content'] = self.tinfoil._reconvert_type(value['_content'], value['_connector_origtype'])
del value['_connector_origtype']
if '_connector_overrides' in value:
overrides = value['_connector_overrides']
del value['_connector_overrides']
return value, overrides
def getKeys(self):
return set(self.tinfoil.run_command('dataStoreConnectorGetKeys', self.dsindex))
def getVarHistory(self, name):
return self.tinfoil.run_command('dataStoreConnectorGetVarHistory', self.dsindex, name)
def expandPythonRef(self, varname, expr, d):
ds = bb.remotedata.RemoteDatastores.transmit_datastore(d)
ret = self.tinfoil.run_command('dataStoreConnectorExpandPythonRef', ds, varname, expr)
return ret
def setVar(self, varname, value):
if self.dsindex is None:
self.tinfoil.run_command('setVariable', varname, value)
else:
# Not currently implemented - indicate that setting should
# be redirected to local side
return True
def setVarFlag(self, varname, flagname, value):
if self.dsindex is None:
self.tinfoil.run_command('dataStoreConnectorSetVarFlag', self.dsindex, varname, flagname, value)
else:
# Not currently implemented - indicate that setting should
# be redirected to local side
return True
def delVar(self, varname):
if self.dsindex is None:
self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname)
else:
# Not currently implemented - indicate that setting should
# be redirected to local side
return True
def delVarFlag(self, varname, flagname):
if self.dsindex is None:
self.tinfoil.run_command('dataStoreConnectorDelVar', self.dsindex, varname, flagname)
else:
# Not currently implemented - indicate that setting should
# be redirected to local side
return True
def renameVar(self, name, newname):
if self.dsindex is None:
self.tinfoil.run_command('dataStoreConnectorRenameVar', self.dsindex, name, newname)
else:
# Not currently implemented - indicate that setting should
# be redirected to local side
return True
class TinfoilCookerAdapter:
"""
Provide an adapter for existing code that expects to access a cooker object via Tinfoil,
since now Tinfoil is on the client side it no longer has direct access.
"""
class TinfoilCookerCollectionAdapter:
""" cooker.collection adapter """
def __init__(self, tinfoil):
self.tinfoil = tinfoil
def get_file_appends(self, fn):
return self.tinfoil.get_file_appends(fn)
def __getattr__(self, name):
if name == 'overlayed':
return self.tinfoil.get_overlayed_recipes()
elif name == 'bbappends':
return self.tinfoil.run_command('getAllAppends')
else:
raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
class TinfoilRecipeCacheAdapter:
""" cooker.recipecache adapter """
def __init__(self, tinfoil):
self.tinfoil = tinfoil
self._cache = {}
def get_pkg_pn_fn(self):
pkg_pn = defaultdict(list, self.tinfoil.run_command('getRecipes') or [])
pkg_fn = {}
for pn, fnlist in pkg_pn.items():
for fn in fnlist:
pkg_fn[fn] = pn
self._cache['pkg_pn'] = pkg_pn
self._cache['pkg_fn'] = pkg_fn
def __getattr__(self, name):
# Grab these only when they are requested since they aren't always used
if name in self._cache:
return self._cache[name]
elif name == 'pkg_pn':
self.get_pkg_pn_fn()
return self._cache[name]
elif name == 'pkg_fn':
self.get_pkg_pn_fn()
return self._cache[name]
elif name == 'deps':
attrvalue = defaultdict(list, self.tinfoil.run_command('getRecipeDepends') or [])
elif name == 'rundeps':
attrvalue = defaultdict(lambda: defaultdict(list), self.tinfoil.run_command('getRuntimeDepends') or [])
elif name == 'runrecs':
attrvalue = defaultdict(lambda: defaultdict(list), self.tinfoil.run_command('getRuntimeRecommends') or [])
elif name == 'pkg_pepvpr':
attrvalue = self.tinfoil.run_command('getRecipeVersions') or {}
elif name == 'inherits':
attrvalue = self.tinfoil.run_command('getRecipeInherits') or {}
elif name == 'bbfile_priority':
attrvalue = self.tinfoil.run_command('getBbFilePriority') or {}
elif name == 'pkg_dp':
attrvalue = self.tinfoil.run_command('getDefaultPreference') or {}
elif name == 'fn_provides':
attrvalue = self.tinfoil.run_command('getRecipeProvides') or {}
elif name == 'packages':
attrvalue = self.tinfoil.run_command('getRecipePackages') or {}
elif name == 'packages_dynamic':
attrvalue = self.tinfoil.run_command('getRecipePackagesDynamic') or {}
elif name == 'rproviders':
attrvalue = self.tinfoil.run_command('getRProviders') or {}
else:
raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
self._cache[name] = attrvalue
return attrvalue
def __init__(self, tinfoil):
self.tinfoil = tinfoil
self.collection = self.TinfoilCookerCollectionAdapter(tinfoil)
self.recipecaches = {}
# FIXME all machines
self.recipecaches[''] = self.TinfoilRecipeCacheAdapter(tinfoil)
self._cache = {}
def __getattr__(self, name):
# Grab these only when they are requested since they aren't always used
if name in self._cache:
return self._cache[name]
elif name == 'skiplist':
attrvalue = self.tinfoil.get_skipped_recipes()
elif name == 'bbfile_config_priorities':
ret = self.tinfoil.run_command('getLayerPriorities')
bbfile_config_priorities = []
for collection, pattern, regex, pri in ret:
bbfile_config_priorities.append((collection, pattern, re.compile(regex), pri))
attrvalue = bbfile_config_priorities
else:
raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
self._cache[name] = attrvalue
return attrvalue
def findBestProvider(self, pn):
return self.tinfoil.find_best_provider(pn)
class TinfoilRecipeInfo:
"""
Provides a convenient representation of the cached information for a single recipe.
Some attributes are set on construction, others are read on-demand (which internally
may result in a remote procedure call to the bitbake server the first time).
Note that only information which is cached is available through this object - if
you need other variable values you will need to parse the recipe using
Tinfoil.parse_recipe().
"""
def __init__(self, recipecache, d, pn, fn, fns):
self._recipecache = recipecache
self._d = d
self.pn = pn
self.fn = fn
self.fns = fns
self.inherit_files = recipecache.inherits[fn]
self.depends = recipecache.deps[fn]
(self.pe, self.pv, self.pr) = recipecache.pkg_pepvpr[fn]
self._cached_packages = None
self._cached_rprovides = None
self._cached_packages_dynamic = None
def __getattr__(self, name):
if name == 'alternates':
return [x for x in self.fns if x != self.fn]
elif name == 'rdepends':
return self._recipecache.rundeps[self.fn]
elif name == 'rrecommends':
return self._recipecache.runrecs[self.fn]
elif name == 'provides':
return self._recipecache.fn_provides[self.fn]
elif name == 'packages':
if self._cached_packages is None:
self._cached_packages = []
for pkg, fns in self._recipecache.packages.items():
if self.fn in fns:
self._cached_packages.append(pkg)
return self._cached_packages
elif name == 'packages_dynamic':
if self._cached_packages_dynamic is None:
self._cached_packages_dynamic = []
for pkg, fns in self._recipecache.packages_dynamic.items():
if self.fn in fns:
self._cached_packages_dynamic.append(pkg)
return self._cached_packages_dynamic
elif name == 'rprovides':
if self._cached_rprovides is None:
self._cached_rprovides = []
for pkg, fns in self._recipecache.rproviders.items():
if self.fn in fns:
self._cached_rprovides.append(pkg)
return self._cached_rprovides
else:
raise AttributeError("%s instance has no attribute '%s'" % (self.__class__.__name__, name))
def inherits(self, only_recipe=False):
"""
Get the inherited classes for a recipe. Returns the class names only.
Parameters:
only_recipe: True to return only the classes inherited by the recipe
itself, False to return all classes inherited within
the context for the recipe (which includes globally
inherited classes).
"""
if only_recipe:
global_inherit = [x for x in (self._d.getVar('BBINCLUDED') or '').split() if x.endswith('.bbclass')]
else:
global_inherit = []
for clsfile in self.inherit_files:
if only_recipe and clsfile in global_inherit:
continue
clsname = os.path.splitext(os.path.basename(clsfile))[0]
yield clsname
def __str__(self):
return '%s' % self.pn
class Tinfoil:
"""
Tinfoil - an API for scripts and utilities to query
BitBake internals and perform build operations.
"""
def __init__(self, output=sys.stdout, tracking=False):
# Needed to avoid deprecation warnings with python 2.6
warnings.filterwarnings("ignore", category=DeprecationWarning)
def __init__(self, output=sys.stdout, tracking=False, setup_logging=True):
"""
Create a new tinfoil object.
Parameters:
output: specifies where console output should be sent. Defaults
to sys.stdout.
tracking: True to enable variable history tracking, False to
disable it (default). Enabling this has a minor
performance impact so typically it isn't enabled
unless you need to query variable history.
setup_logging: True to setup a logger so that things like
bb.warn() will work immediately and timeout warnings
are visible; False to let BitBake do this itself.
"""
# Set up logging
self.logger = logging.getLogger('BitBake')
self.config_data = None
self.cooker = None
self.tracking = tracking
self.ui_module = None
self.server_connection = None
self.recipes_parsed = False
self.quiet = 0
self.oldhandlers = self.logger.handlers[:]
if setup_logging:
# This is the *client-side* logger, nothing to do with
# logging messages from the server
bb.msg.logger_create('BitBake', output)
self.localhandlers = []
for handler in self.logger.handlers:
if handler not in self.oldhandlers:
self.localhandlers.append(handler)
self._log_hdlr = logging.StreamHandler(output)
bb.msg.addDefaultlogFilter(self._log_hdlr)
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
if output.isatty():
format.enable_color()
self._log_hdlr.setFormatter(format)
self.logger.addHandler(self._log_hdlr)
self.config = CookerConfiguration()
configparams = TinfoilConfigParameters(parse_only=True)
self.config.setConfigParameters(configparams)
self.config.setServerRegIdleCallback(self.register_idle_function)
features = []
if tracking:
features.append(CookerFeatures.BASEDATASTORE_TRACKING)
cleanedvars = bb.utils.clean_environment()
self.cooker = BBCooker(self.config, features)
self.config_data = self.cooker.data
bb.providers.logger.setLevel(logging.ERROR)
self.cooker_data = None
for k in cleanedvars:
os.environ[k] = cleanedvars[k]
def register_idle_function(self, function, data):
pass
def __enter__(self):
return self
@@ -338,290 +68,30 @@ class Tinfoil:
def __exit__(self, type, value, traceback):
self.shutdown()
def prepare(self, config_only=False, config_params=None, quiet=0, extra_features=None):
"""
Prepares the underlying BitBake system to be used via tinfoil.
This function must be called prior to calling any of the other
functions in the API.
NOTE: if you call prepare() you must absolutely call shutdown()
before your code terminates. You can use a "with" block to ensure
this happens e.g.
with bb.tinfoil.Tinfoil() as tinfoil:
tinfoil.prepare()
...
Parameters:
config_only: True to read only the configuration and not load
the cache / parse recipes. This is useful if you just
want to query the value of a variable at the global
level or you want to do anything else that doesn't
involve knowing anything about the recipes in the
current configuration. False loads the cache / parses
recipes.
config_params: optionally specify your own configuration
parameters. If not specified an instance of
TinfoilConfigParameters will be created internally.
quiet: quiet level controlling console output - equivalent
to bitbake's -q/--quiet option. Default of 0 gives
the same output level as normal bitbake execution.
extra_features: extra features to be added to the feature
set requested from the server. See
CookerFeatures._feature_list for possible
features.
"""
self.quiet = quiet
if self.tracking:
extrafeatures = [bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING]
else:
extrafeatures = []
if extra_features:
extrafeatures += extra_features
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.ui_module = ui_module
# Ensure the path to bitbake's bin directory is in PATH so that things like
# bitbake-worker can be run (usually this is the case, but it doesn't have to be)
path = os.getenv('PATH').split(':')
bitbakebinpath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '..', 'bin'))
for entry in path:
if entry.endswith(os.sep):
entry = entry[:-1]
if os.path.abspath(entry) == bitbakebinpath:
break
else:
path.insert(0, bitbakebinpath)
os.environ['PATH'] = ':'.join(path)
if self.server_connection:
_server_connections.append(self.server_connection)
if config_only:
config_params.updateToServer(self.server_connection.connection, os.environ.copy())
self.run_command('parseConfiguration')
else:
self.run_actions(config_params)
self.recipes_parsed = True
self.config_data = bb.data.init()
connector = TinfoilDataStoreConnector(self, None)
self.config_data.setVar('_remote_data', connector)
self.cooker = TinfoilCookerAdapter(self)
self.cooker_data = self.cooker.recipecaches['']
else:
raise Exception('Failed to start bitbake server')
def run_actions(self, config_params):
"""
Run the actions specified in config_params through the UI.
"""
ret = self.ui_module.main(self.server_connection.connection, self.server_connection.events, config_params)
if ret:
raise TinfoilUIException(ret)
def parseRecipes(self):
"""
Legacy function - use parse_recipes() instead.
"""
self.parse_recipes()
sys.stderr.write("Parsing recipes..")
self.logger.setLevel(logging.WARNING)
def parse_recipes(self):
"""
Load information on all recipes. Normally you should specify
config_only=False when calling prepare() instead of using this
function; this function is designed for situations where you need
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)
self.run_actions(config_params)
self.recipes_parsed = True
try:
while self.cooker.state in (state.initial, state.parsing):
self.cooker.updateCache()
except KeyboardInterrupt:
self.cooker.shutdown()
self.cooker.updateCache()
sys.exit(2)
def run_command(self, command, *params):
"""
Run a command on the server (as implemented in bb.command).
Note that there are two types of command - synchronous and
asynchronous; in order to receive the results of asynchronous
commands you will need to set an appropriate event mask
using set_event_mask() and listen for the result using
wait_event() - with the correct event mask you'll at least get
bb.command.CommandCompleted and possibly other events before
that depending on the command.
"""
if not self.server_connection:
raise Exception('Not connected to server (did you call .prepare()?)')
self.logger.setLevel(logging.INFO)
sys.stderr.write("done.\n")
commandline = [command]
if params:
commandline.extend(params)
result = self.server_connection.connection.runCommand(commandline)
if result[1]:
raise TinfoilCommandFailed(result[1])
return result[0]
self.cooker_data = self.cooker.recipecaches['']
def set_event_mask(self, eventlist):
"""Set the event mask which will be applied within wait_event()"""
if not self.server_connection:
raise Exception('Not connected to server (did you call .prepare()?)')
llevel, debug_domains = bb.msg.constructLogOptions()
ret = self.run_command('setEventMask', self.server_connection.connection.getEventHandle(), llevel, debug_domains, eventlist)
if not ret:
raise Exception('setEventMask failed')
def wait_event(self, timeout=0):
"""
Wait for an event from the server for the specified time.
A timeout of 0 means don't wait if there are no events in the queue.
Returns the next event in the queue or None if the timeout was
reached. Note that in order to recieve any events you will
first need to set the internal event mask using set_event_mask()
(otherwise whatever event mask the UI set up will be in effect).
"""
if not self.server_connection:
raise Exception('Not connected to server (did you call .prepare()?)')
return self.server_connection.events.waitEvent(timeout)
def get_overlayed_recipes(self):
"""
Find recipes which are overlayed (i.e. where recipes exist in multiple layers)
"""
return defaultdict(list, self.run_command('getOverlayedRecipes'))
def get_skipped_recipes(self):
"""
Find recipes which were skipped (i.e. SkipRecipe was raised
during parsing).
"""
return OrderedDict(self.run_command('getSkippedRecipes'))
def get_all_providers(self):
return defaultdict(list, self.run_command('allProviders'))
def find_providers(self):
return self.run_command('findProviders')
def find_best_provider(self, pn):
return self.run_command('findBestProvider', pn)
def get_runtime_providers(self, rdep):
return self.run_command('getRuntimeProviders', rdep)
def get_recipe_file(self, pn):
"""
Get the file name for the specified recipe/target. Raises
bb.providers.NoProvider if there is no match or the recipe was
skipped.
"""
best = self.find_best_provider(pn)
if not best or (len(best) > 3 and not best[3]):
skiplist = self.get_skipped_recipes()
taskdata = bb.taskdata.TaskData(None, skiplist=skiplist)
skipreasons = taskdata.get_reasons(pn)
if skipreasons:
raise bb.providers.NoProvider('%s is unavailable:\n %s' % (pn, ' \n'.join(skipreasons)))
def prepare(self, config_only = False):
if not self.cooker_data:
if config_only:
self.cooker.parseConfiguration()
self.cooker_data = self.cooker.recipecaches['']
else:
raise bb.providers.NoProvider('Unable to find any recipe file matching "%s"' % pn)
return best[3]
def get_file_appends(self, fn):
"""
Find the bbappends for a recipe file
"""
return self.run_command('getFileAppends', fn)
def all_recipes(self, mc='', sort=True):
"""
Enable iterating over all recipes in the current configuration.
Returns an iterator over TinfoilRecipeInfo objects created on demand.
Parameters:
mc: The multiconfig, default of '' uses the main configuration.
sort: True to sort recipes alphabetically (default), False otherwise
"""
recipecache = self.cooker.recipecaches[mc]
if sort:
recipes = sorted(recipecache.pkg_pn.items())
else:
recipes = recipecache.pkg_pn.items()
for pn, fns in recipes:
prov = self.find_best_provider(pn)
recipe = TinfoilRecipeInfo(recipecache,
self.config_data,
pn=pn,
fn=prov[3],
fns=fns)
yield recipe
def all_recipe_files(self, mc='', variants=True, preferred_only=False):
"""
Enable iterating over all recipe files in the current configuration.
Returns an iterator over file paths.
Parameters:
mc: The multiconfig, default of '' uses the main configuration.
variants: True to include variants of recipes created through
BBCLASSEXTEND (default) or False to exclude them
preferred_only: True to include only the preferred recipe where
multiple exist providing the same PN, False to list
all recipes
"""
recipecache = self.cooker.recipecaches[mc]
if preferred_only:
files = []
for pn in recipecache.pkg_pn.keys():
prov = self.find_best_provider(pn)
files.append(prov[3])
else:
files = recipecache.pkg_fn.keys()
for fn in sorted(files):
if not variants and fn.startswith('virtual:'):
continue
yield fn
def get_recipe_info(self, pn, mc=''):
"""
Get information on a specific recipe in the current configuration by name (PN).
Returns a TinfoilRecipeInfo object created on demand.
Parameters:
mc: The multiconfig, default of '' uses the main configuration.
"""
recipecache = self.cooker.recipecaches[mc]
prov = self.find_best_provider(pn)
fn = prov[3]
if fn:
actual_pn = recipecache.pkg_fn[fn]
recipe = TinfoilRecipeInfo(recipecache,
self.config_data,
pn=actual_pn,
fn=fn,
fns=recipecache.pkg_pn[actual_pn])
return recipe
else:
return None
def parse_recipe(self, pn):
"""
Parse the specified recipe and return a datastore object
representing the environment for the recipe.
"""
fn = self.get_recipe_file(pn)
return self.parse_recipe_file(fn)
self.parseRecipes()
def parse_recipe_file(self, fn, appends=True, appendlist=None, config_data=None):
"""
@@ -638,263 +108,43 @@ class Tinfoil:
specify config_data then you cannot use a virtual
specification for fn.
"""
if self.tracking:
# Enable history tracking just for the parse operation
self.run_command('enableDataTracking')
try:
if appends and appendlist == []:
appends = False
if config_data:
dctr = bb.remotedata.RemoteDatastores.transmit_datastore(config_data)
dscon = self.run_command('parseRecipeFile', fn, appends, appendlist, dctr)
if appends and appendlist == []:
appends = False
if appends:
if appendlist:
appendfiles = appendlist
else:
dscon = self.run_command('parseRecipeFile', fn, appends, appendlist)
if dscon:
return self._reconvert_type(dscon, 'DataStoreConnectionHandle')
else:
return None
finally:
if self.tracking:
self.run_command('disableDataTracking')
def build_file(self, buildfile, task, internal=True):
"""
Runs the specified task for just a single recipe (i.e. no dependencies).
This is equivalent to bitbake -b, except with the default internal=True
no warning about dependencies will be produced, normal info messages
from the runqueue will be silenced and BuildInit, BuildStarted and
BuildCompleted events will not be fired.
"""
return self.run_command('buildFile', buildfile, task, internal)
def build_targets(self, targets, task=None, handle_events=True, extra_events=None, event_callback=None):
"""
Builds the specified targets. This is equivalent to a normal invocation
of bitbake. Has built-in event handling which is enabled by default and
can be extended if needed.
Parameters:
targets:
One or more targets to build. Can be a list or a
space-separated string.
task:
The task to run; if None then the value of BB_DEFAULT_TASK
will be used. Default None.
handle_events:
True to handle events in a similar way to normal bitbake
invocation with knotty; False to return immediately (on the
assumption that the caller will handle the events instead).
Default True.
extra_events:
An optional list of events to add to the event mask (if
handle_events=True). If you add events here you also need
to specify a callback function in event_callback that will
handle the additional events. Default None.
event_callback:
An optional function taking a single parameter which
will be called first upon receiving any event (if
handle_events=True) so that the caller can override or
extend the event handling. Default None.
"""
if isinstance(targets, str):
targets = targets.split()
if not task:
task = self.config_data.getVar('BB_DEFAULT_TASK')
if handle_events:
# A reasonable set of default events matching up with those we handle below
eventmask = [
'bb.event.BuildStarted',
'bb.event.BuildCompleted',
'logging.LogRecord',
'bb.event.NoProvider',
'bb.command.CommandCompleted',
'bb.command.CommandFailed',
'bb.build.TaskStarted',
'bb.build.TaskFailed',
'bb.build.TaskSucceeded',
'bb.build.TaskFailedSilent',
'bb.build.TaskProgress',
'bb.runqueue.runQueueTaskStarted',
'bb.runqueue.sceneQueueTaskStarted',
'bb.event.ProcessStarted',
'bb.event.ProcessProgress',
'bb.event.ProcessFinished',
]
if extra_events:
eventmask.extend(extra_events)
ret = self.set_event_mask(eventmask)
includelogs = self.config_data.getVar('BBINCLUDELOGS')
loglines = self.config_data.getVar('BBINCLUDELOGS_LINES')
ret = self.run_command('buildTargets', targets, task)
if handle_events:
result = False
# Borrowed from knotty, instead somewhat hackily we use the helper
# as the object to store "shutdown" on
helper = bb.ui.uihelper.BBUIHelper()
# We set up logging optionally in the constructor so now we need to
# grab the handlers to pass to TerminalFilter
console = None
errconsole = None
for handler in self.logger.handlers:
if isinstance(handler, logging.StreamHandler):
if handler.stream == sys.stdout:
console = handler
elif handler.stream == sys.stderr:
errconsole = handler
format_str = "%(levelname)s: %(message)s"
format = bb.msg.BBLogFormatter(format_str)
helper.shutdown = 0
parseprogress = None
termfilter = bb.ui.knotty.TerminalFilter(helper, helper, console, errconsole, format, quiet=self.quiet)
try:
while True:
try:
event = self.wait_event(0.25)
if event:
if event_callback and event_callback(event):
continue
if helper.eventHandler(event):
if isinstance(event, bb.build.TaskFailedSilent):
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
if isinstance(event, bb.event.ProcessStarted):
if self.quiet > 1:
continue
parseprogress = bb.ui.knotty.new_progress(event.processname, event.total)
parseprogress.start(False)
continue
if isinstance(event, bb.event.ProcessProgress):
if self.quiet > 1:
continue
if parseprogress:
parseprogress.update(event.progress)
else:
bb.warn("Got ProcessProgress event for someting that never started?")
continue
if isinstance(event, bb.event.ProcessFinished):
if self.quiet > 1:
continue
if parseprogress:
parseprogress.finish()
parseprogress = None
continue
if isinstance(event, bb.command.CommandCompleted):
result = True
break
if isinstance(event, bb.command.CommandFailed):
self.logger.error(str(event))
result = False
break
if isinstance(event, logging.LogRecord):
if event.taskpid == 0 or event.levelno > logging.INFO:
self.logger.handle(event)
continue
if isinstance(event, bb.event.NoProvider):
self.logger.error(str(event))
result = False
break
elif helper.shutdown > 1:
break
termfilter.updateFooter()
except KeyboardInterrupt:
termfilter.clearFooter()
if helper.shutdown == 1:
print("\nSecond Keyboard Interrupt, stopping...\n")
ret = self.run_command("stateForceShutdown")
if ret and ret[2]:
self.logger.error("Unable to cleanly stop: %s" % ret[2])
elif helper.shutdown == 0:
print("\nKeyboard Interrupt, closing down...\n")
interrupted = True
ret = self.run_command("stateShutdown")
if ret and ret[2]:
self.logger.error("Unable to cleanly shutdown: %s" % ret[2])
helper.shutdown = helper.shutdown + 1
termfilter.clearFooter()
finally:
termfilter.finish()
if helper.failed_tasks:
result = False
return result
if not hasattr(self.cooker, 'collection'):
raise Exception('You must call tinfoil.prepare() with config_only=False in order to get bbappends')
appendfiles = self.cooker.collection.get_file_appends(fn)
else:
return ret
appendfiles = None
if config_data:
# We have to use a different function here if we're passing in a datastore
localdata = bb.data.createCopy(config_data)
envdata = bb.cache.parse_recipe(localdata, fn, appendfiles)['']
else:
# Use the standard path
parser = bb.cache.NoCache(self.cooker.databuilder)
envdata = parser.loadDataFull(fn, appendfiles)
return envdata
def shutdown(self):
"""
Shut down tinfoil. Disconnects from the server and gracefully
releases any associated resources. You must call this function if
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
self.cooker.shutdown(force=True)
self.cooker.post_serve()
self.cooker.unlockBitbake()
self.logger.removeHandler(self._log_hdlr)
# 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)
class TinfoilConfigParameters(ConfigParameters):
def _reconvert_type(self, obj, origtypename):
"""
Convert an object back to the right type, in the case
that marshalling has changed it (especially with xmlrpc)
"""
supported_types = {
'set': set,
'DataStoreConnectionHandle': bb.command.DataStoreConnectionHandle,
}
origtype = supported_types.get(origtypename, None)
if origtype is None:
raise Exception('Unsupported type "%s"' % origtypename)
if type(obj) == origtype:
newobj = obj
elif isinstance(obj, dict):
# New style class
newobj = origtype()
for k,v in obj.items():
setattr(newobj, k, v)
else:
# Assume we can coerce the type
newobj = origtype(obj)
if isinstance(newobj, bb.command.DataStoreConnectionHandle):
connector = TinfoilDataStoreConnector(self, newobj.dsindex)
newobj = bb.data.init()
newobj.setVar('_remote_data', connector)
return newobj
class TinfoilConfigParameters(BitBakeConfigParameters):
def __init__(self, config_only, **options):
def __init__(self, **options):
self.initial_options = options
# Apply some sane defaults
if not 'parse_only' in options:
self.initial_options['parse_only'] = not config_only
#if not 'status_only' in options:
# self.initial_options['status_only'] = config_only
if not 'ui' in options:
self.initial_options['ui'] = 'knotty'
if not 'argv' in options:
self.initial_options['argv'] = []
super(TinfoilConfigParameters, self).__init__()
def parseCommandLine(self, argv=None):
# We don't want any parameters parsed from the command line
opts = super(TinfoilConfigParameters, self).parseCommandLine([])
for key, val in self.initial_options.items():
setattr(opts[0], key, val)
return opts
def parseCommandLine(self, argv=sys.argv):
class DummyOptions:
def __init__(self, initial_options):
for key, val in initial_options.items():
setattr(self, key, val)
return DummyOptions(self.initial_options), None

View File

@@ -42,12 +42,10 @@ from orm.models import Variable, VariableHistory
from orm.models import Package, Package_File, Target_Installed_Package, Target_File
from orm.models import Task_Dependency, Package_Dependency
from orm.models import Recipe_Dependency, Provides
from orm.models import Project, CustomImagePackage
from orm.models import Project, CustomImagePackage, CustomImageRecipe
from orm.models import signal_runbuilds
from bldcontrol.models import BuildEnvironment, BuildRequest
from bldcontrol.models import BRLayer
from bldcontrol import bbcontroller
from bb.msg import BBLogFormatter as formatter
from django.db import models
@@ -363,6 +361,11 @@ class ORMWrapper(object):
def get_update_layer_version_object(self, build_obj, layer_obj, layer_version_information):
if isinstance(layer_obj, Layer_Version):
# Special case the toaster-custom-images layer which is created
# on the fly so don't update the values which may cause the layer
# to be duplicated on a future get_or_create
if layer_obj.layer.name == CustomImageRecipe.LAYER_NAME:
return layer_obj
# We already found our layer version for this build so just
# update it with the new build information
logger.debug("We found our layer from toaster")
@@ -381,8 +384,8 @@ class ORMWrapper(object):
local_path=layer_version_information['local_path'],
)
logger.debug("Created new layer version %s for build history",
layer_copy.layer.name)
logger.info("created new historical layer version %d",
layer_copy.pk)
self.layer_version_built.append(layer_copy)
@@ -438,33 +441,48 @@ class ORMWrapper(object):
else:
br_id, be_id = brbe.split(":")
# Find the layer version by matching the layer event information
# against the metadata we have in Toaster
# find layer by checkout path;
from bldcontrol import bbcontroller
bc = bbcontroller.getBuildEnvironmentController(pk = be_id)
try:
br_layer = BRLayer.objects.get(req=br_id,
name=layer_information['name'])
return br_layer.layer_version
except (BRLayer.MultipleObjectsReturned, BRLayer.DoesNotExist):
# There are multiple of the same layer name or the name
# hasn't been determined by the toaster.bbclass layer
# so let's filter by the local_path
bc = bbcontroller.getBuildEnvironmentController(pk=be_id)
for br_layer in BRLayer.objects.filter(req=br_id):
if br_layer.giturl and \
layer_information['local_path'].endswith(
bc.getGitCloneDirectory(br_layer.giturl,
br_layer.commit)):
return br_layer.layer_version
# we might have a race condition here, as the project layers may change between the build trigger and the actual build execution
# but we can only match on the layer name, so the worst thing can happen is a mis-identification of the layer, not a total failure
if br_layer.local_source_dir == \
layer_information['local_path']:
return br_layer.layer_version
# note that this is different
buildrequest = BuildRequest.objects.get(pk = br_id)
for brl in buildrequest.brlayer_set.all():
if brl.local_source_dir:
localdirname = os.path.join(brl.local_source_dir,
brl.dirpath)
else:
localdirname = os.path.join(bc.getGitCloneDirectory(brl.giturl, brl.commit), brl.dirpath)
# we get a relative path, unless running in HEAD mode where the path is absolute
if not localdirname.startswith("/"):
localdirname = os.path.join(bc.be.sourcedir, localdirname)
#logger.debug(1, "Localdirname %s lcal_path %s" % (localdirname, layer_information['local_path']))
if localdirname.startswith(layer_information['local_path']):
# If the build request came from toaster this field
# should contain the information from the layer_version
# That created this build request.
if brl.layer_version:
return brl.layer_version
# This might be a local layer (i.e. no git info) so try
# matching local_source_dir
if brl.local_source_dir and brl.local_source_dir == layer_information["local_path"]:
return brl.layer_version
# we matched the BRLayer, but we need the layer_version that generated this BR; reverse of the Project.schedule_build()
#logger.debug(1, "Matched %s to BRlayer %s" % (pformat(layer_information["local_path"]), localdirname))
for pl in buildrequest.project.projectlayer_set.filter(layercommit__layer__name = brl.name):
if pl.layercommit.layer.vcs_url == brl.giturl :
layer = pl.layercommit.layer
layer.save()
return layer
raise NotExisting("Unidentified layer %s" % pformat(layer_information))
# We've reached the end of our search and couldn't find the layer
# we can continue but some data may be missing
raise NotExisting("Unidentified layer %s" %
pformat(layer_information))
def save_target_file_information(self, build_obj, target_obj, filedata):
assert isinstance(build_obj, Build)
@@ -719,11 +737,7 @@ class ORMWrapper(object):
def save_build_package_information(self, build_obj, package_info, recipes,
built_package):
# assert isinstance(build_obj, Build)
if not 'PN' in package_info.keys():
# no package data to save (e.g. 'OPKGN'="lib64-*"|"lib32-*")
return None
# assert isinstance(build_obj, Build)
# create and save the object
pname = package_info['PKG']
@@ -862,12 +876,6 @@ class MockEvent(object):
self.pathname = None
self.lineno = None
def getMessage(self):
"""
Simulate LogRecord message return
"""
return self.msg
class BuildInfoHelper(object):
""" This class gathers the build information from the server and sends it
@@ -975,10 +983,9 @@ class BuildInfoHelper(object):
return task_information
def _get_layer_version_for_dependency(self, pathRE):
""" Returns the layer in the toaster db that has a full regex
match to the pathRE. pathRE - the layer path passed as a regex in the
event. It is created in cooker.py as a collection for the layer
priorities.
""" Returns the layer in the toaster db that has a full regex match to the pathRE.
pathRE - the layer path passed as a regex in the event. It is created in
cooker.py as a collection for the layer priorities.
"""
self._ensure_build()
@@ -986,31 +993,19 @@ class BuildInfoHelper(object):
assert isinstance(layer_version, Layer_Version)
return len(layer_version.local_path)
# Our paths don't append a trailing slash
if pathRE.endswith("/"):
pathRE = pathRE[:-1]
p = re.compile(pathRE)
path=re.sub(r'[$^]',r'',pathRE)
# Heuristics: we always match recipe to the deepest layer path in
# the discovered layers
for lvo in sorted(self.orm_wrapper.layer_version_objects,
reverse=True, key=_sort_longest_path):
if p.fullmatch(os.path.abspath(lvo.local_path)):
# we don't care if we match the trailing slashes
p = re.compile(re.sub("/[^/]*?$","",pathRE))
# Heuristics: we always match recipe to the deepest layer path in the discovered layers
for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_sort_longest_path):
if p.fullmatch(lvo.local_path):
return lvo
if lvo.layer.local_source_dir:
if p.fullmatch(os.path.abspath(lvo.layer.local_source_dir)):
if p.fullmatch(lvo.layer.local_source_dir):
return lvo
if 0 == path.find(lvo.local_path):
# sub-layer path inside existing layer
return lvo
#if we get here, we didn't read layers correctly; dump whatever information we have on the error log
logger.warning("Could not match layer dependency for path %s : %s", path, self.orm_wrapper.layer_version_objects)
# if we get here, we didn't read layers correctly;
# dump whatever information we have on the error log
logger.warning("Could not match layer dependency for path %s : %s",
pathRE,
self.orm_wrapper.layer_version_objects)
return None
def _get_layer_version_for_path(self, path):
self._ensure_build()
@@ -1273,14 +1268,6 @@ class BuildInfoHelper(object):
candidates = [x for x in self.internal_state['taskdata'].keys() if x.endswith(identifier)]
if len(candidates) == 1:
identifier = candidates[0]
elif len(candidates) > 1 and hasattr(event,'_package'):
if 'native-' in event._package:
identifier = 'native:' + identifier
if 'nativesdk-' in event._package:
identifier = 'nativesdk:' + identifier
candidates = [x for x in self.internal_state['taskdata'].keys() if x.endswith(identifier)]
if len(candidates) == 1:
identifier = candidates[0]
assert identifier in self.internal_state['taskdata']
identifierlist = identifier.split(":")
@@ -1411,9 +1398,9 @@ class BuildInfoHelper(object):
for lv in event._depgraph['layer-priorities']:
(_, path, _, priority) = lv
layer_version_obj = self._get_layer_version_for_dependency(path)
if layer_version_obj:
layer_version_obj.priority = priority
layer_version_obj.save()
assert layer_version_obj is not None
layer_version_obj.priority = priority
layer_version_obj.save()
# save recipe information
self.internal_state['recipes'] = {}
@@ -1678,36 +1665,6 @@ class BuildInfoHelper(object):
break
return endswith
def scan_task_artifacts(self, event):
"""
The 'TaskArtifacts' event passes the manifest file content for the
tasks 'do_deploy', 'do_image_complete', 'do_populate_sdk', and
'do_populate_sdk_ext'. The first two will be implemented later.
"""
task_vars = BuildInfoHelper._get_data_from_event(event)
task_name = task_vars['task'][task_vars['task'].find(':')+1:]
task_artifacts = task_vars['artifacts']
if task_name in ['do_populate_sdk', 'do_populate_sdk_ext']:
targets = [target for target in self.internal_state['targets'] \
if target.task == task_name[3:]]
if not targets:
logger.warning("scan_task_artifacts: SDK targets not found: %s\n", task_name)
return
for artifact_path in task_artifacts:
if not os.path.isfile(artifact_path):
logger.warning("scan_task_artifacts: artifact file not found: %s\n", artifact_path)
continue
for target in targets:
# don't record the file if it's already been added
# to this target
matching_files = TargetSDKFile.objects.filter(
target=target, file_name=artifact_path)
if matching_files.count() == 0:
artifact_size = os.stat(artifact_path).st_size
self.orm_wrapper.save_target_sdk_file(
target, artifact_path, artifact_size)
def _get_image_files(self, deploy_dir_image, image_name, image_file_extensions):
"""
Find files in deploy_dir_image whose basename starts with the

358
bitbake/lib/bb/ui/depexp.py Normal file
View File

@@ -0,0 +1,358 @@
#
# BitBake Graphical GTK based Dependency Explorer
#
# Copyright (C) 2007 Ross Burton
# Copyright (C) 2007 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject
from multiprocessing import Queue
import threading
from xmlrpc import client
import time
import bb
import bb.event
# Package Model
(COL_PKG_NAME) = (0)
# Dependency Model
(TYPE_DEP, TYPE_RDEP) = (0, 1)
(COL_DEP_TYPE, COL_DEP_PARENT, COL_DEP_PACKAGE) = (0, 1, 2)
class PackageDepView(Gtk.TreeView):
def __init__(self, model, dep_type, label):
Gtk.TreeView.__init__(self)
self.current = None
self.dep_type = dep_type
self.filter_model = model.filter_new()
self.filter_model.set_visible_func(self._filter, data=None)
self.set_model(self.filter_model)
self.append_column(Gtk.TreeViewColumn(label, Gtk.CellRendererText(), text=COL_DEP_PACKAGE))
def _filter(self, model, iter, data):
this_type = model[iter][COL_DEP_TYPE]
package = model[iter][COL_DEP_PARENT]
if this_type != self.dep_type: return False
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class PackageReverseDepView(Gtk.TreeView):
def __init__(self, model, label):
Gtk.TreeView.__init__(self)
self.current = None
self.filter_model = model.filter_new()
self.filter_model.set_visible_func(self._filter)
self.set_model(self.filter_model)
self.append_column(Gtk.TreeViewColumn(label, Gtk.CellRendererText(), text=COL_DEP_PARENT))
def _filter(self, model, iter, data):
package = model[iter][COL_DEP_PACKAGE]
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class DepExplorer(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_title("Dependency Explorer")
self.set_default_size(500, 500)
self.connect("delete-event", Gtk.main_quit)
# Create the data models
self.pkg_model = Gtk.ListStore(GObject.TYPE_STRING)
self.pkg_model.set_sort_column_id(COL_PKG_NAME, Gtk.SortType.ASCENDING)
self.depends_model = Gtk.ListStore(GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_STRING)
self.depends_model.set_sort_column_id(COL_DEP_PACKAGE, Gtk.SortType.ASCENDING)
pane = Gtk.HPaned()
pane.set_position(250)
self.add(pane)
# The master list of packages
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.pkg_treeview = Gtk.TreeView(self.pkg_model)
self.pkg_treeview.get_selection().connect("changed", self.on_cursor_changed)
column = Gtk.TreeViewColumn("Package", Gtk.CellRendererText(), text=COL_PKG_NAME)
self.pkg_treeview.append_column(column)
pane.add1(scrolled)
scrolled.add(self.pkg_treeview)
box = Gtk.VBox(homogeneous=True, spacing=4)
# Runtime Depends
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.rdep_treeview = PackageDepView(self.depends_model, TYPE_RDEP, "Runtime Depends")
self.rdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
scrolled.add(self.rdep_treeview)
box.add(scrolled)
# Build Depends
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.dep_treeview = PackageDepView(self.depends_model, TYPE_DEP, "Build Depends")
self.dep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
scrolled.add(self.dep_treeview)
box.add(scrolled)
pane.add2(box)
# Reverse Depends
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.revdep_treeview = PackageReverseDepView(self.depends_model, "Reverse Depends")
self.revdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PARENT)
scrolled.add(self.revdep_treeview)
box.add(scrolled)
pane.add2(box)
self.show_all()
def on_package_activated(self, treeview, path, column, data_col):
model = treeview.get_model()
package = model.get_value(model.get_iter(path), data_col)
pkg_path = []
def finder(model, path, iter, needle):
package = model.get_value(iter, COL_PKG_NAME)
if package == needle:
pkg_path.append(path)
return True
else:
return False
self.pkg_model.foreach(finder, package)
if pkg_path:
self.pkg_treeview.get_selection().select_path(pkg_path[0])
self.pkg_treeview.scroll_to_cell(pkg_path[0])
def on_cursor_changed(self, selection):
(model, it) = selection.get_selected()
if it is None:
current_package = None
else:
current_package = model.get_value(it, COL_PKG_NAME)
self.rdep_treeview.set_current_package(current_package)
self.dep_treeview.set_current_package(current_package)
self.revdep_treeview.set_current_package(current_package)
def parse(self, depgraph):
for package in depgraph["pn"]:
self.pkg_model.insert(0, (package,))
for package in depgraph["depends"]:
for depend in depgraph["depends"][package]:
self.depends_model.insert (0, (TYPE_DEP, package, depend))
for package in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][package]:
self.depends_model.insert (0, (TYPE_RDEP, package, rdepend))
class gtkthread(threading.Thread):
quit = threading.Event()
def __init__(self, shutdown):
threading.Thread.__init__(self)
self.setDaemon(True)
self.shutdown = shutdown
if not Gtk.init_check()[0]:
sys.stderr.write("Gtk+ init failed. Make sure DISPLAY variable is set.\n")
gtkthread.quit.set()
def run(self):
GObject.threads_init()
Gdk.threads_init()
Gtk.main()
gtkthread.quit.set()
def main(server, eventHandler, params):
shutdown = 0
gtkgui = gtkthread(shutdown)
gtkgui.start()
try:
params.updateFromServer(server)
cmdline = params.parseActions()
if not cmdline:
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
return 1
if 'msg' in cmdline and cmdline['msg']:
print(cmdline['msg'])
return 1
cmdline = cmdline['action']
if not cmdline or cmdline[0] != "generateDotGraph":
print("This UI requires the -g option")
return 1
ret, error = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
if error:
print("Error running command '%s': %s" % (cmdline, error))
return 1
elif ret != True:
print("Error running command '%s': returned %s" % (cmdline, ret))
return 1
except client.Fault as x:
print("XMLRPC Fault getting commandline:\n %s" % x)
return
if gtkthread.quit.isSet():
return
Gdk.threads_enter()
dep = DepExplorer()
bardialog = Gtk.Dialog(parent=dep,
flags=Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT)
bardialog.set_default_size(400, 50)
box = bardialog.get_content_area()
pbar = Gtk.ProgressBar()
box.pack_start(pbar, True, True, 0)
bardialog.show_all()
bardialog.connect("delete-event", Gtk.main_quit)
Gdk.threads_leave()
progress_total = 0
while True:
try:
event = eventHandler.waitEvent(0.25)
if gtkthread.quit.isSet():
_, error = server.runCommand(["stateForceShutdown"])
if error:
print('Unable to cleanly stop: %s' % error)
break
if event is None:
continue
if isinstance(event, bb.event.CacheLoadStarted):
progress_total = event.total
Gdk.threads_enter()
bardialog.set_title("Loading Cache")
pbar.set_fraction(0.0)
Gdk.threads_leave()
if isinstance(event, bb.event.CacheLoadProgress):
x = event.current
Gdk.threads_enter()
pbar.set_fraction(x * 1.0 / progress_total)
Gdk.threads_leave()
continue
if isinstance(event, bb.event.CacheLoadCompleted):
continue
if isinstance(event, bb.event.ParseStarted):
progress_total = event.total
if progress_total == 0:
continue
Gdk.threads_enter()
pbar.set_fraction(0.0)
bardialog.set_title("Processing recipes")
Gdk.threads_leave()
if isinstance(event, bb.event.ParseProgress):
x = event.current
Gdk.threads_enter()
pbar.set_fraction(x * 1.0 / progress_total)
Gdk.threads_leave()
continue
if isinstance(event, bb.event.ParseCompleted):
Gdk.threads_enter()
bardialog.set_title("Generating dependency tree")
Gdk.threads_leave()
continue
if isinstance(event, bb.event.DepTreeGenerated):
Gdk.threads_enter()
bardialog.hide()
dep.parse(event._depgraph)
Gdk.threads_leave()
if isinstance(event, bb.command.CommandCompleted):
continue
if isinstance(event, bb.event.NoProvider):
if event._runtime:
r = "R"
else:
r = ""
extra = ''
if not event._reasons:
if event._close_matches:
extra = ". Close matches:\n %s" % '\n '.join(event._close_matches)
if event._dependees:
print("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s" % r, event._item, ", ".join(event._dependees), r, extra)
else:
print("Nothing %sPROVIDES '%s'%s" % (r, event._item, extra))
if event._reasons:
for reason in event._reasons:
print(reason)
_, error = server.runCommand(["stateShutdown"])
if error:
print('Unable to cleanly shutdown: %s' % error)
break
if isinstance(event, bb.command.CommandFailed):
print("Command execution failed: %s" % event.error)
return event.exitcode
if isinstance(event, bb.command.CommandExit):
return event.exitcode
if isinstance(event, bb.cooker.CookerExit):
break
continue
except EnvironmentError as ioerror:
# ignore interrupted io
if ioerror.args[0] == 4:
pass
except KeyboardInterrupt:
if shutdown == 2:
print("\nThird Keyboard Interrupt, exit.\n")
break
if shutdown == 1:
print("\nSecond Keyboard Interrupt, stopping...\n")
_, error = server.runCommand(["stateForceShutdown"])
if error:
print('Unable to cleanly stop: %s' % error)
if shutdown == 0:
print("\nKeyboard Interrupt, closing down...\n")
_, error = server.runCommand(["stateShutdown"])
if error:
print('Unable to cleanly shutdown: %s' % error)
shutdown = shutdown + 1
pass

View File

@@ -75,8 +75,10 @@ class BBProgress(progressbar.ProgressBar):
extrastr = str(extra)
if extrastr[0] != ' ':
extrastr = ' ' + extrastr
if extrastr[-1] != ' ':
extrastr += ' '
else:
extrastr = ''
extrastr = ' '
self.widgets[self.extrapos] = extrastr
def _need_update(self):
@@ -207,10 +209,8 @@ class TerminalFilter(object):
self.interactive = False
bb.note("Unable to use interactive mode for this terminal, using fallback")
return
if console:
console.addFilter(InteractConsoleLogFilter(self, format))
if errconsole:
errconsole.addFilter(InteractConsoleLogFilter(self, format))
console.addFilter(InteractConsoleLogFilter(self, format))
errconsole.addFilter(InteractConsoleLogFilter(self, format))
self.main_progress = None
@@ -284,7 +284,7 @@ class TerminalFilter(object):
content = self.main_progress.update(progress)
print('')
lines = 1 + int(len(content) / (self.columns + 1))
if self.quiet == 0:
if not self.quiet:
for tasknum, task in enumerate(tasks[:(self.rows - 2)]):
if isinstance(task, tuple):
pbar, progress, rate, start_time = task
@@ -312,33 +312,7 @@ class TerminalFilter(object):
fd = sys.stdin.fileno()
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
def print_event_log(event, includelogs, loglines, termfilter):
# FIXME refactor this out further
logfile = event.logfile
if logfile and os.path.exists(logfile):
termfilter.clearFooter()
bb.error("Logfile of failure stored in: %s" % logfile)
if includelogs and not event.errprinted:
print("Log data follows:")
f = open(logfile, "r")
lines = []
while True:
l = f.readline()
if l == '':
break
l = l.rstrip()
if loglines:
lines.append(' | %s' % l)
if len(lines) > int(loglines):
lines.pop(0)
else:
print('| %s' % l)
f.close()
if lines:
for line in lines:
print(line)
def _log_settings_from_server(server, observe_only):
def _log_settings_from_server(server):
# Get values of variables which control our output
includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
if error:
@@ -348,11 +322,7 @@ def _log_settings_from_server(server, observe_only):
if error:
logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
raise BaseException(error)
if observe_only:
cmd = 'getVariable'
else:
cmd = 'getSetVariable'
consolelogfile, error = server.runCommand([cmd, "BB_CONSOLELOG"])
consolelogfile, error = server.runCommand(["getSetVariable", "BB_CONSOLELOG"])
if error:
logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
raise BaseException(error)
@@ -370,10 +340,7 @@ _evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.Lo
def main(server, eventHandler, params, tf = TerminalFilter):
if not params.observe_only:
params.updateToServer(server, os.environ.copy())
includelogs, loglines, consolelogfile = _log_settings_from_server(server, params.observe_only)
includelogs, loglines, consolelogfile = _log_settings_from_server(server)
if sys.stdin.isatty() and sys.stdout.isatty():
log_exec_tty = True
@@ -386,19 +353,15 @@ def main(server, eventHandler, params, tf = TerminalFilter):
errconsole = logging.StreamHandler(sys.stderr)
format_str = "%(levelname)s: %(message)s"
format = bb.msg.BBLogFormatter(format_str)
if params.options.quiet == 0:
forcelevel = None
elif params.options.quiet > 2:
forcelevel = bb.msg.BBLogFormatter.ERROR
if params.options.quiet:
bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut, bb.msg.BBLogFormatter.WARNING)
else:
forcelevel = bb.msg.BBLogFormatter.WARNING
bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut, forcelevel)
bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut)
bb.msg.addDefaultlogFilter(errconsole, bb.msg.BBLogFilterStdErr)
console.setFormatter(format)
errconsole.setFormatter(format)
if not bb.msg.has_console_handler(logger):
logger.addHandler(console)
logger.addHandler(errconsole)
logger.addHandler(console)
logger.addHandler(errconsole)
bb.utils.set_process_name("KnottyUI")
@@ -427,6 +390,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
universe = False
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.")
@@ -502,11 +466,11 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
# Prefix task messages with recipe/task
if event.taskpid in helper.running_tasks and event.levelno != format.PLAIN:
if event.taskpid in helper.running_tasks:
taskinfo = helper.running_tasks[event.taskpid]
event.msg = taskinfo['title'] + ': ' + event.msg
if hasattr(event, 'fn'):
event.msg = event.fn + ': ' + event.msg
event.msg = event.fn + ': ' + event.msg
logger.handle(event)
continue
@@ -515,52 +479,62 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
if isinstance(event, bb.build.TaskFailed):
return_value = 1
print_event_log(event, includelogs, loglines, termfilter)
logfile = event.logfile
if logfile and os.path.exists(logfile):
termfilter.clearFooter()
bb.error("Logfile of failure stored in: %s" % logfile)
if includelogs and not event.errprinted:
print("Log data follows:")
f = open(logfile, "r")
lines = []
while True:
l = f.readline()
if l == '':
break
l = l.rstrip()
if loglines:
lines.append(' | %s' % l)
if len(lines) > int(loglines):
lines.pop(0)
else:
print('| %s' % l)
f.close()
if lines:
for line in lines:
print(line)
if isinstance(event, bb.build.TaskBase):
logger.info(event._message)
continue
if isinstance(event, bb.event.ParseStarted):
if params.options.quiet > 1:
continue
if event.total == 0:
continue
parseprogress = new_progress("Parsing recipes", event.total).start()
continue
if isinstance(event, bb.event.ParseProgress):
if params.options.quiet > 1:
continue
if parseprogress:
parseprogress.update(event.current)
else:
bb.warn("Got ParseProgress event for parsing that never started?")
continue
if isinstance(event, bb.event.ParseCompleted):
if params.options.quiet > 1:
continue
if not parseprogress:
continue
parseprogress.finish()
pasreprogress = None
if params.options.quiet == 0:
if not params.options.quiet:
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)))
continue
if isinstance(event, bb.event.CacheLoadStarted):
if params.options.quiet > 1:
continue
cacheprogress = new_progress("Loading cache", event.total).start()
continue
if isinstance(event, bb.event.CacheLoadProgress):
if params.options.quiet > 1:
continue
cacheprogress.update(event.current)
continue
if isinstance(event, bb.event.CacheLoadCompleted):
if params.options.quiet > 1:
continue
cacheprogress.finish()
if params.options.quiet == 0:
if not params.options.quiet:
print("Loaded %d entries from dependency cache." % event.num_entries)
continue
@@ -568,7 +542,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
return_value = event.exitcode
if event.error:
errors = errors + 1
logger.error(str(event))
logger.error("Command execution failed: %s", event.error)
main.shutdown = 2
continue
if isinstance(event, bb.command.CommandExit):
@@ -579,16 +553,39 @@ def main(server, eventHandler, params, tf = TerminalFilter):
main.shutdown = 2
continue
if isinstance(event, bb.event.MultipleProviders):
logger.info(str(event))
logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "",
event._item,
", ".join(event._candidates))
rtime = ""
if event._is_runtime:
rtime = "R"
logger.info("consider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, event._item))
continue
if isinstance(event, bb.event.NoProvider):
if event._runtime:
r = "R"
else:
r = ""
extra = ''
if not event._reasons:
if event._close_matches:
extra = ". Close matches:\n %s" % '\n '.join(event._close_matches)
# For universe builds, only show these as warnings, not errors
h = logger.warning
if not universe:
return_value = 1
errors = errors + 1
logger.error(str(event))
h = logger.error
if event._dependees:
h("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s", r, event._item, ", ".join(event._dependees), r, extra)
else:
logger.warning(str(event))
h("Nothing %sPROVIDES '%s'%s", r, event._item, extra)
if event._reasons:
for reason in event._reasons:
h("%s", reason)
continue
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
@@ -610,33 +607,29 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if isinstance(event, bb.runqueue.runQueueTaskFailed):
return_value = 1
taskfailures.append(event.taskstring)
logger.error(str(event))
logger.error("Task (%s) failed with exit code '%s'",
event.taskstring, event.exitcode)
continue
if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
logger.warning(str(event))
logger.warning("Setscene task (%s) failed with exit code '%s' - real task will be run instead",
event.taskstring, event.exitcode)
continue
if isinstance(event, bb.event.DepTreeGenerated):
continue
if isinstance(event, bb.event.ProcessStarted):
if params.options.quiet > 1:
continue
parseprogress = new_progress(event.processname, event.total)
parseprogress.start(False)
continue
if isinstance(event, bb.event.ProcessProgress):
if params.options.quiet > 1:
continue
if parseprogress:
parseprogress.update(event.progress)
else:
bb.warn("Got ProcessProgress event for someting that never started?")
continue
if isinstance(event, bb.event.ProcessFinished):
if params.options.quiet > 1:
continue
if parseprogress:
parseprogress.finish()
parseprogress = None
@@ -647,7 +640,6 @@ def main(server, eventHandler, params, tf = TerminalFilter):
bb.event.MetadataEvent,
bb.event.StampUpdate,
bb.event.ConfigParsed,
bb.event.MultiConfigParsed,
bb.event.RecipeParsed,
bb.event.RecipePreFinalise,
bb.runqueue.runQueueEvent,
@@ -655,7 +647,6 @@ def main(server, eventHandler, params, tf = TerminalFilter):
bb.event.OperationCompleted,
bb.event.OperationProgress,
bb.event.DiskFull,
bb.event.HeartbeatEvent,
bb.build.TaskProgress)):
continue
@@ -709,7 +700,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if return_value and errors:
summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
"\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
if summary and params.options.quiet == 0:
if summary and not params.options.quiet:
print(summary)
if interrupted:

View File

@@ -297,7 +297,7 @@ class NCursesUI:
# bb.error("log data follows (%s)" % logfile)
# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
# if number_of_lines:
# subprocess.check_call('tail -n%s %s' % (number_of_lines, logfile), shell=True)
# subprocess.call('tail -n%s %s' % (number_of_lines, logfile), shell=True)
# else:
# f = open(logfile, "r")
# while True:
@@ -315,7 +315,7 @@ class NCursesUI:
# also allow them to now exit with a single ^C
shutdown = 2
if isinstance(event, bb.command.CommandFailed):
mw.appendText(str(event))
mw.appendText("Command execution failed: %s" % event.error)
time.sleep(2)
exitflag = True
if isinstance(event, bb.command.CommandExit):

View File

@@ -1,328 +0,0 @@
#
# BitBake Graphical GTK based Dependency Explorer
#
# Copyright (C) 2007 Ross Burton
# Copyright (C) 2007 - 2008 Richard Purdie
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject
from multiprocessing import Queue
import threading
from xmlrpc import client
import time
import bb
import bb.event
# Package Model
(COL_PKG_NAME) = (0)
# Dependency Model
(TYPE_DEP, TYPE_RDEP) = (0, 1)
(COL_DEP_TYPE, COL_DEP_PARENT, COL_DEP_PACKAGE) = (0, 1, 2)
class PackageDepView(Gtk.TreeView):
def __init__(self, model, dep_type, label):
Gtk.TreeView.__init__(self)
self.current = None
self.dep_type = dep_type
self.filter_model = model.filter_new()
self.filter_model.set_visible_func(self._filter, data=None)
self.set_model(self.filter_model)
self.append_column(Gtk.TreeViewColumn(label, Gtk.CellRendererText(), text=COL_DEP_PACKAGE))
def _filter(self, model, iter, data):
this_type = model[iter][COL_DEP_TYPE]
package = model[iter][COL_DEP_PARENT]
if this_type != self.dep_type: return False
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class PackageReverseDepView(Gtk.TreeView):
def __init__(self, model, label):
Gtk.TreeView.__init__(self)
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()
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))
def _filter(self, model, iter, data):
package = model[iter][COL_DEP_PACKAGE]
return package == self.current
def set_current_package(self, package):
self.current = package
self.filter_model.refilter()
class DepExplorer(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_title("Task Dependency Explorer")
self.set_default_size(500, 500)
self.connect("delete-event", Gtk.main_quit)
# Create the data models
self.pkg_model = Gtk.ListStore(GObject.TYPE_STRING)
self.pkg_model.set_sort_column_id(COL_PKG_NAME, Gtk.SortType.ASCENDING)
self.depends_model = Gtk.ListStore(GObject.TYPE_INT, GObject.TYPE_STRING, GObject.TYPE_STRING)
self.depends_model.set_sort_column_id(COL_DEP_PACKAGE, Gtk.SortType.ASCENDING)
pane = Gtk.HPaned()
pane.set_position(250)
self.add(pane)
# The master list of packages
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.pkg_treeview = Gtk.TreeView(self.pkg_model)
self.pkg_treeview.get_selection().connect("changed", self.on_cursor_changed)
column = Gtk.TreeViewColumn("Package", Gtk.CellRendererText(), text=COL_PKG_NAME)
self.pkg_treeview.append_column(column)
pane.add1(scrolled)
scrolled.add(self.pkg_treeview)
box = Gtk.VBox(homogeneous=True, spacing=4)
# Task Depends
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.dep_treeview = PackageDepView(self.depends_model, TYPE_DEP, "Dependencies")
self.dep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PACKAGE)
scrolled.add(self.dep_treeview)
box.add(scrolled)
pane.add2(box)
# Reverse Task Depends
scrolled = Gtk.ScrolledWindow()
scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
scrolled.set_shadow_type(Gtk.ShadowType.IN)
self.revdep_treeview = PackageReverseDepView(self.depends_model, "Dependent Tasks")
self.revdep_treeview.connect("row-activated", self.on_package_activated, COL_DEP_PARENT)
scrolled.add(self.revdep_treeview)
box.add(scrolled)
pane.add2(box)
self.show_all()
def on_package_activated(self, treeview, path, column, data_col):
model = treeview.get_model()
package = model.get_value(model.get_iter(path), data_col)
pkg_path = []
def finder(model, path, iter, needle):
package = model.get_value(iter, COL_PKG_NAME)
if package == needle:
pkg_path.append(path)
return True
else:
return False
self.pkg_model.foreach(finder, package)
if pkg_path:
self.pkg_treeview.get_selection().select_path(pkg_path[0])
self.pkg_treeview.scroll_to_cell(pkg_path[0])
def on_cursor_changed(self, selection):
(model, it) = selection.get_selected()
if it is None:
current_package = None
else:
current_package = model.get_value(it, COL_PKG_NAME)
self.dep_treeview.set_current_package(current_package)
self.revdep_treeview.set_current_package(current_package)
def parse(self, depgraph):
for task in depgraph["tdepends"]:
self.pkg_model.insert(0, (task,))
for depend in depgraph["tdepends"][task]:
self.depends_model.insert (0, (TYPE_DEP, task, depend))
class gtkthread(threading.Thread):
quit = threading.Event()
def __init__(self, shutdown):
threading.Thread.__init__(self)
self.setDaemon(True)
self.shutdown = shutdown
if not Gtk.init_check()[0]:
sys.stderr.write("Gtk+ init failed. Make sure DISPLAY variable is set.\n")
gtkthread.quit.set()
def run(self):
GObject.threads_init()
Gdk.threads_init()
Gtk.main()
gtkthread.quit.set()
def main(server, eventHandler, params):
shutdown = 0
gtkgui = gtkthread(shutdown)
gtkgui.start()
try:
params.updateFromServer(server)
cmdline = params.parseActions()
if not cmdline:
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
return 1
if 'msg' in cmdline and cmdline['msg']:
print(cmdline['msg'])
return 1
cmdline = cmdline['action']
if not cmdline or cmdline[0] != "generateDotGraph":
print("This UI requires the -g option")
return 1
ret, error = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
if error:
print("Error running command '%s': %s" % (cmdline, error))
return 1
elif ret != True:
print("Error running command '%s': returned %s" % (cmdline, ret))
return 1
except client.Fault as x:
print("XMLRPC Fault getting commandline:\n %s" % x)
return
if gtkthread.quit.isSet():
return
Gdk.threads_enter()
dep = DepExplorer()
bardialog = Gtk.Dialog(parent=dep,
flags=Gtk.DialogFlags.MODAL|Gtk.DialogFlags.DESTROY_WITH_PARENT)
bardialog.set_default_size(400, 50)
box = bardialog.get_content_area()
pbar = Gtk.ProgressBar()
box.pack_start(pbar, True, True, 0)
bardialog.show_all()
bardialog.connect("delete-event", Gtk.main_quit)
Gdk.threads_leave()
progress_total = 0
while True:
try:
event = eventHandler.waitEvent(0.25)
if gtkthread.quit.isSet():
_, error = server.runCommand(["stateForceShutdown"])
if error:
print('Unable to cleanly stop: %s' % error)
break
if event is None:
continue
if isinstance(event, bb.event.CacheLoadStarted):
progress_total = event.total
Gdk.threads_enter()
bardialog.set_title("Loading Cache")
pbar.set_fraction(0.0)
Gdk.threads_leave()
if isinstance(event, bb.event.CacheLoadProgress):
x = event.current
Gdk.threads_enter()
pbar.set_fraction(x * 1.0 / progress_total)
Gdk.threads_leave()
continue
if isinstance(event, bb.event.CacheLoadCompleted):
continue
if isinstance(event, bb.event.ParseStarted):
progress_total = event.total
if progress_total == 0:
continue
Gdk.threads_enter()
pbar.set_fraction(0.0)
bardialog.set_title("Processing recipes")
Gdk.threads_leave()
if isinstance(event, bb.event.ParseProgress):
x = event.current
Gdk.threads_enter()
pbar.set_fraction(x * 1.0 / progress_total)
Gdk.threads_leave()
continue
if isinstance(event, bb.event.ParseCompleted):
Gdk.threads_enter()
bardialog.set_title("Generating dependency tree")
Gdk.threads_leave()
continue
if isinstance(event, bb.event.DepTreeGenerated):
Gdk.threads_enter()
bardialog.hide()
dep.parse(event._depgraph)
Gdk.threads_leave()
if isinstance(event, bb.command.CommandCompleted):
continue
if isinstance(event, bb.event.NoProvider):
print(str(event))
_, error = server.runCommand(["stateShutdown"])
if error:
print('Unable to cleanly shutdown: %s' % error)
break
if isinstance(event, bb.command.CommandFailed):
print(str(event))
return event.exitcode
if isinstance(event, bb.command.CommandExit):
return event.exitcode
if isinstance(event, bb.cooker.CookerExit):
break
continue
except EnvironmentError as ioerror:
# ignore interrupted io
if ioerror.args[0] == 4:
pass
except KeyboardInterrupt:
if shutdown == 2:
print("\nThird Keyboard Interrupt, exit.\n")
break
if shutdown == 1:
print("\nSecond Keyboard Interrupt, stopping...\n")
_, error = server.runCommand(["stateForceShutdown"])
if error:
print('Unable to cleanly stop: %s' % error)
if shutdown == 0:
print("\nKeyboard Interrupt, closing down...\n")
_, error = server.runCommand(["stateShutdown"])
if error:
print('Unable to cleanly shutdown: %s' % error)
shutdown = shutdown + 1
pass

View File

@@ -168,9 +168,6 @@ def main(server, eventHandler, params):
logger.warning("buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details.")
build_history_enabled = False
if not "buildstats" in inheritlist.split(" "):
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())
@@ -236,9 +233,6 @@ def main(server, eventHandler, params):
# pylint: disable=protected-access
# the code will look into the protected variables of the event; no easy way around this
if isinstance(event, bb.event.HeartbeatEvent):
continue
if isinstance(event, bb.event.ParseStarted):
if not (build_log and build_log_file_path):
build_log, build_log_file_path = _open_build_log(log_dir)
@@ -320,13 +314,29 @@ def main(server, eventHandler, params):
if isinstance(event, bb.event.CacheLoadCompleted):
continue
if isinstance(event, bb.event.MultipleProviders):
logger.info(str(event))
logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "",
event._item,
", ".join(event._candidates))
logger.info("consider defining a PREFERRED_PROVIDER entry to match %s", event._item)
continue
if isinstance(event, bb.event.NoProvider):
errors = errors + 1
text = str(event)
if event._runtime:
r = "R"
else:
r = ""
if event._dependees:
text = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (r, event._item, ", ".join(event._dependees), r)
else:
text = "Nothing %sPROVIDES '%s'" % (r, event._item)
logger.error(text)
if event._reasons:
for reason in event._reasons:
logger.error("%s", reason)
text += reason
buildinfohelper.store_log_error(text)
continue
@@ -348,7 +358,8 @@ def main(server, eventHandler, params):
if isinstance(event, bb.runqueue.runQueueTaskFailed):
buildinfohelper.update_and_store_task(event)
taskfailures.append(event.taskstring)
logger.error(str(event))
logger.error("Task (%s) failed with exit code '%s'",
event.taskstring, event.exitcode)
continue
if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted, bb.runqueue.sceneQueueTaskFailed)):
@@ -365,7 +376,7 @@ def main(server, eventHandler, params):
if isinstance(event, bb.command.CommandFailed):
errors += 1
errorcode = 1
logger.error(str(event))
logger.error("Command execution failed: %s", event.error)
elif isinstance(event, bb.event.BuildCompleted):
buildinfohelper.scan_image_artifacts()
buildinfohelper.clone_required_sdk_artifacts()
@@ -421,7 +432,9 @@ def main(server, eventHandler, params):
elif event.type == "SetBRBE":
buildinfohelper.brbe = buildinfohelper._get_data_from_event(event)
elif event.type == "TaskArtifacts":
buildinfohelper.scan_task_artifacts(event)
# not implemented yet
# see https://bugzilla.yoctoproject.org/show_bug.cgi?id=10283 for details
pass
elif event.type == "OSErrorException":
logger.error(event)
else:

View File

@@ -61,9 +61,6 @@ class BBUIHelper:
self.running_tasks[event.pid]['progress'] = event.progress
self.running_tasks[event.pid]['rate'] = event.rate
self.needUpdate = True
else:
return False
return True
def getTasks(self):
self.needUpdate = False

View File

@@ -187,7 +187,7 @@ def explode_deps(s):
#r[-1] += ' ' + ' '.join(j)
return r
def explode_dep_versions2(s, *, sort=True):
def explode_dep_versions2(s):
"""
Take an RDEPENDS style string of format:
"DEPEND1 (optional version) DEPEND2 (optional version) ..."
@@ -250,8 +250,7 @@ def explode_dep_versions2(s, *, sort=True):
if not (i in r and r[i]):
r[lastdep] = []
if sort:
r = collections.OrderedDict(sorted(r.items(), key=lambda x: x[0]))
r = collections.OrderedDict(sorted(r.items(), key=lambda x: x[0]))
return r
def explode_dep_versions(s):
@@ -524,8 +523,12 @@ def md5_file(filename):
"""
Return the hex string representation of the MD5 checksum of filename.
"""
import hashlib
m = hashlib.md5()
try:
import hashlib
m = hashlib.md5()
except ImportError:
import md5
m = md5.new()
with open(filename, "rb") as f:
for line in f:
@@ -535,9 +538,14 @@ def md5_file(filename):
def sha256_file(filename):
"""
Return the hex string representation of the 256-bit SHA checksum of
filename.
filename. On Python 2.4 this will return None, so callers will need to
handle that by either skipping SHA checks, or running a standalone sha256sum
binary.
"""
import hashlib
try:
import hashlib
except ImportError:
return None
s = hashlib.sha256()
with open(filename, "rb") as f:
@@ -549,7 +557,10 @@ def sha1_file(filename):
"""
Return the hex string representation of the SHA1 checksum of the filename
"""
import hashlib
try:
import hashlib
except ImportError:
return None
s = hashlib.sha1()
with open(filename, "rb") as f:
@@ -654,7 +665,7 @@ def build_environment(d):
for var in bb.data.keys(d):
export = d.getVarFlag(var, "export", False)
if export:
os.environ[var] = d.getVar(var) or ""
os.environ[var] = d.getVar(var, True) or ""
def _check_unsafe_delete_path(path):
"""
@@ -681,7 +692,7 @@ def remove(path, recurse=False):
if _check_unsafe_delete_path(path):
raise Exception('bb.utils.remove: called with dangerous path "%s" and recurse=True, refusing to delete!' % path)
# shutil.rmtree(name) would be ideal but its too slow
subprocess.check_call(['rm', '-rf'] + glob.glob(path))
subprocess.call(['rm', '-rf'] + glob.glob(path))
return
for name in glob.glob(path):
try:
@@ -772,14 +783,13 @@ def movefile(src, dest, newmtime = None, sstat = None):
return None
renamefailed = 1
# os.rename needs to know the dest path ending with file name
# so append the file name to a path only if it's a dir specified
srcfname = os.path.basename(src)
destpath = os.path.join(dest, srcfname) if os.path.isdir(dest) \
else dest
if sstat[stat.ST_DEV] == dstat[stat.ST_DEV]:
try:
# os.rename needs to know the dest path ending with file name
# so append the file name to a path only if it's a dir specified
srcfname = os.path.basename(src)
destpath = os.path.join(dest, srcfname) if os.path.isdir(dest) \
else dest
os.rename(src, destpath)
renamefailed = 0
except Exception as e:
@@ -793,8 +803,8 @@ def movefile(src, dest, newmtime = None, sstat = None):
didcopy = 0
if stat.S_ISREG(sstat[stat.ST_MODE]):
try: # For safety copy then move it over.
shutil.copyfile(src, destpath + "#new")
os.rename(destpath + "#new", destpath)
shutil.copyfile(src, dest + "#new")
os.rename(dest + "#new", dest)
didcopy = 1
except Exception as e:
print('movefile: copy', src, '->', dest, 'failed.', e)
@@ -807,17 +817,17 @@ def movefile(src, dest, newmtime = None, sstat = None):
return None # failure
try:
if didcopy:
os.lchown(destpath, sstat[stat.ST_UID], sstat[stat.ST_GID])
os.chmod(destpath, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
os.lchown(dest, sstat[stat.ST_UID], sstat[stat.ST_GID])
os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
os.unlink(src)
except Exception as e:
print("movefile: Failed to chown/chmod/unlink", dest, e)
return None
if newmtime:
os.utime(destpath, (newmtime, newmtime))
os.utime(dest, (newmtime, newmtime))
else:
os.utime(destpath, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
os.utime(dest, (sstat[stat.ST_ATIME], sstat[stat.ST_MTIME]))
newmtime = sstat[stat.ST_MTIME]
return newmtime
@@ -901,20 +911,11 @@ def copyfile(src, dest, newmtime = None, sstat = None):
newmtime = sstat[stat.ST_MTIME]
return newmtime
def which(path, item, direction = 0, history = False, executable=False):
def which(path, item, direction = 0, history = False):
"""
Locate `item` in the list of paths `path` (colon separated string like $PATH).
If `direction` is non-zero then the list is reversed.
If `history` is True then the list of candidates also returned as result,history.
If `executable` is True then the candidate has to be an executable file,
otherwise the candidate simply has to exist.
Locate a file in a PATH
"""
if executable:
is_candidate = lambda p: os.path.isfile(p) and os.access(p, os.X_OK)
else:
is_candidate = lambda p: os.path.exists(p)
hist = []
paths = (path or "").split(':')
if direction != 0:
@@ -923,7 +924,7 @@ def which(path, item, direction = 0, history = False, executable=False):
for p in paths:
next = os.path.join(p, item)
hist.append(next)
if is_candidate(next):
if os.path.exists(next):
if not os.path.isabs(next):
next = os.path.abspath(next)
if history:
@@ -952,7 +953,7 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
Arguments:
variable -- the variable name. This will be fetched and expanded (using
d.getVar(variable)) and then split into a set().
d.getVar(variable, True)) 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().
@@ -965,7 +966,7 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
d -- the data store.
"""
val = d.getVar(variable)
val = d.getVar(variable, True)
if not val:
return falsevalue
val = set(val.split())
@@ -978,7 +979,7 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
return falsevalue
def contains_any(variable, checkvalues, truevalue, falsevalue, d):
val = d.getVar(variable)
val = d.getVar(variable, True)
if not val:
return falsevalue
val = set(val.split())
@@ -990,30 +991,6 @@ def contains_any(variable, checkvalues, truevalue, falsevalue, d):
return truevalue
return falsevalue
def filter(variable, checkvalues, d):
"""Return all words in the variable that are present in the checkvalues.
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().
d -- the data store.
"""
val = d.getVar(variable)
if not val:
return ''
val = set(val.split())
if isinstance(checkvalues, str):
checkvalues = set(checkvalues.split())
else:
checkvalues = set(checkvalues)
return ' '.join(sorted(checkvalues & val))
def cpu_count():
return multiprocessing.cpu_count()
@@ -1401,10 +1378,10 @@ def edit_bblayers_conf(bblayers_conf, add, remove):
def get_file_layer(filename, d):
"""Determine the collection (as defined by a layer's layer.conf file) containing the specified file"""
collections = (d.getVar('BBFILE_COLLECTIONS') or '').split()
collections = (d.getVar('BBFILE_COLLECTIONS', True) or '').split()
collection_res = {}
for collection in collections:
collection_res[collection] = d.getVar('BBFILE_PATTERN_%s' % collection) or ''
collection_res[collection] = d.getVar('BBFILE_PATTERN_%s' % collection, True) or ''
def path_to_layer(path):
# Use longest path so we handle nested layers
@@ -1417,7 +1394,7 @@ def get_file_layer(filename, d):
return match
result = None
bbfiles = (d.getVar('BBFILES') or '').split()
bbfiles = (d.getVar('BBFILES', True) or '').split()
bbfilesmatch = False
for bbfilesentry in bbfiles:
if fnmatch.fnmatch(filename, bbfilesentry):
@@ -1494,7 +1471,7 @@ def export_proxies(d):
if v in os.environ.keys():
exported = True
else:
v_proxy = d.getVar(v)
v_proxy = d.getVar(v, True)
if v_proxy is not None:
os.environ[v] = v_proxy
exported = True
@@ -1504,7 +1481,7 @@ 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)
fp, pathname, description = imp.find_module(name, [pluginpath])
try:
return imp.load_module(name, fp, pathname, description)
@@ -1512,7 +1489,7 @@ def load_plugins(logger, plugins, pluginpath):
if fp:
fp.close()
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)
@@ -1526,14 +1503,3 @@ def load_plugins(logger, plugins, pluginpath):
plugins.append(obj or plugin)
else:
plugins.append(plugin)
class LogCatcher(logging.Handler):
"""Logging handler for collecting logged messages so you can check them later"""
def __init__(self):
self.messages = []
logging.Handler.__init__(self, logging.WARNING)
def emit(self, record):
self.messages.append(bb.build.logformatter.format(record))
def contains(self, message):
return (message in self.messages)

View File

@@ -1,9 +1,7 @@
import fnmatch
import logging
import os
import shutil
import sys
import tempfile
import bb.utils
@@ -18,62 +16,41 @@ def plugin_init(plugins):
class ActionPlugin(LayerPlugin):
def do_add_layer(self, args):
"""Add one or more layers to bblayers.conf."""
layerdirs = [os.path.abspath(ldir) for ldir in args.layerdir]
"""Add a layer to bblayers.conf."""
layerdir = os.path.abspath(args.layerdir)
if not os.path.exists(layerdir):
sys.stderr.write("Specified layer directory doesn't exist\n")
return 1
for layerdir in layerdirs:
if not os.path.exists(layerdir):
sys.stderr.write("Specified layer directory %s doesn't exist\n" % layerdir)
return 1
layer_conf = os.path.join(layerdir, 'conf', 'layer.conf')
if not os.path.exists(layer_conf):
sys.stderr.write("Specified layer directory %s doesn't contain a conf/layer.conf file\n" % layerdir)
return 1
layer_conf = os.path.join(layerdir, 'conf', 'layer.conf')
if not os.path.exists(layer_conf):
sys.stderr.write("Specified layer directory doesn't contain a conf/layer.conf file\n")
return 1
bblayers_conf = os.path.join('conf', 'bblayers.conf')
if not os.path.exists(bblayers_conf):
sys.stderr.write("Unable to find bblayers.conf\n")
return 1
# Back up bblayers.conf to tempdir before we add layers
tempdir = tempfile.mkdtemp()
backup = tempdir + "/bblayers.conf.bak"
shutil.copy2(bblayers_conf, backup)
try:
notadded, _ = bb.utils.edit_bblayers_conf(bblayers_conf, layerdirs, None)
if not (args.force or notadded):
try:
self.tinfoil.parseRecipes()
except bb.tinfoil.TinfoilUIException:
# Restore the back up copy of bblayers.conf
shutil.copy2(backup, bblayers_conf)
bb.fatal("Parse failure with the specified layer added")
else:
for item in notadded:
sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)
finally:
# Remove the back up copy of bblayers.conf
shutil.rmtree(tempdir)
notadded, _ = bb.utils.edit_bblayers_conf(bblayers_conf, layerdir, None)
if notadded:
for item in notadded:
sys.stderr.write("Specified layer %s is already in BBLAYERS\n" % item)
def do_remove_layer(self, args):
"""Remove one or more layers from bblayers.conf."""
"""Remove a layer from bblayers.conf."""
bblayers_conf = os.path.join('conf', 'bblayers.conf')
if not os.path.exists(bblayers_conf):
sys.stderr.write("Unable to find bblayers.conf\n")
return 1
layerdirs = []
for item in args.layerdir:
if item.startswith('*'):
layerdir = item
elif not '/' in item:
layerdir = '*/%s' % item
else:
layerdir = os.path.abspath(item)
layerdirs.append(layerdir)
(_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdirs)
if args.layerdir.startswith('*'):
layerdir = args.layerdir
elif not '/' in args.layerdir:
layerdir = '*/%s' % args.layerdir
else:
layerdir = os.path.abspath(args.layerdir)
(_, notremoved) = bb.utils.edit_bblayers_conf(bblayers_conf, None, layerdir)
if notremoved:
for item in notremoved:
sys.stderr.write("No layers matching %s found in BBLAYERS\n" % item)
@@ -203,7 +180,7 @@ build results (as the layer priority order has effectively changed).
if first_regex:
# Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
bbfiles = str(self.tinfoil.config_data.getVar('BBFILES')).split()
bbfiles = str(self.tinfoil.config_data.getVar('BBFILES', True)).split()
bbfiles_layer = []
for item in bbfiles:
if first_regex.match(item):
@@ -245,10 +222,10 @@ build results (as the layer priority order has effectively changed).
def register_commands(self, sp):
parser_add_layer = self.add_command(sp, 'add-layer', self.do_add_layer, parserecipes=False)
parser_add_layer.add_argument('layerdir', nargs='+', help='Layer directory/directories to add')
parser_add_layer.add_argument('layerdir', help='Layer directory to add')
parser_remove_layer = self.add_command(sp, 'remove-layer', self.do_remove_layer, parserecipes=False)
parser_remove_layer.add_argument('layerdir', nargs='+', help='Layer directory/directories to remove (wildcards allowed, enclose in quotes to avoid shell expansion)')
parser_remove_layer.add_argument('layerdir', help='Layer directory to remove (wildcards allowed, enclose in quotes to avoid shell expansion)')
parser_remove_layer.set_defaults(func=self.do_remove_layer)
parser_flatten = self.add_command(sp, 'flatten', self.do_flatten)

View File

@@ -12,7 +12,7 @@ class LayerPlugin():
def tinfoil_init(self, tinfoil):
self.tinfoil = tinfoil
self.bblayers = (self.tinfoil.config_data.getVar('BBLAYERS') or "").split()
self.bblayers = (self.tinfoil.config_data.getVar('BBLAYERS', True) or "").split()
layerconfs = self.tinfoil.config_data.varhistory.get_variable_items_files('BBFILE_COLLECTIONS', self.tinfoil.config_data)
self.bbfile_collections = {layer: os.path.dirname(os.path.dirname(path)) for layer, path in layerconfs.items()}

View File

@@ -56,7 +56,7 @@ class LayerIndexPlugin(ActionPlugin):
r = conn.getresponse()
if r.status != 200:
raise Exception("Failed to read " + path + ": %d %s" % (r.status, r.reason))
return json.loads(r.read().decode())
return json.loads(r.read())
def get_layer_deps(self, layername, layeritems, layerbranches, layerdependencies, branchnum, selfname=False):
def layeritems_info_id(items_name, layeritems):
@@ -151,7 +151,7 @@ class LayerIndexPlugin(ActionPlugin):
def do_layerindex_fetch(self, args):
"""Fetches a layer from a layer index along with its dependent layers, and adds them to conf/bblayers.conf.
"""
apiurl = self.tinfoil.config_data.getVar('BBLAYERS_LAYERINDEX_URL')
apiurl = self.tinfoil.config_data.getVar('BBLAYERS_LAYERINDEX_URL', True)
if not apiurl:
logger.error("Cannot get BBLAYERS_LAYERINDEX_URL")
return 1
@@ -173,8 +173,8 @@ class LayerIndexPlugin(ActionPlugin):
return 1
ignore_layers = []
for collection in self.tinfoil.config_data.getVar('BBFILE_COLLECTIONS').split():
lname = self.tinfoil.config_data.getVar('BBLAYERS_LAYERINDEX_NAME_%s' % collection)
for collection in self.tinfoil.config_data.getVar('BBFILE_COLLECTIONS', True).split():
lname = self.tinfoil.config_data.getVar('BBLAYERS_LAYERINDEX_NAME_%s' % collection, True)
if lname:
ignore_layers.append(lname)
@@ -225,7 +225,7 @@ class LayerIndexPlugin(ActionPlugin):
printedlayers.append(dependency)
if repourls:
fetchdir = self.tinfoil.config_data.getVar('BBLAYERS_FETCH_DIR')
fetchdir = self.tinfoil.config_data.getVar('BBLAYERS_FETCH_DIR', True)
if not fetchdir:
logger.error("Cannot get BBLAYERS_FETCH_DIR")
return 1
@@ -247,7 +247,6 @@ class LayerIndexPlugin(ActionPlugin):
logger.plain("Adding layer \"%s\" to conf/bblayers.conf" % name)
localargs = argparse.Namespace()
localargs.layerdir = layerdir
localargs.force = args.force
self.do_add_layer(localargs)
else:
break

View File

@@ -5,6 +5,8 @@ import sys
import os
import re
import bb.cache
import bb.providers
import bb.utils
from bblayers.common import LayerPlugin
@@ -60,7 +62,7 @@ are overlayed will also be listed, with a " (skipped)" suffix.
# factor - however, each layer.conf is free to either prepend or append to
# BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
# not be exactly the order present in bblayers.conf either.
bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
bbpath = str(self.tinfoil.config_data.getVar('BBPATH', True))
overlayed_class_found = False
for (classfile, classdirs) in classes.items():
if len(classdirs) > 1:
@@ -112,7 +114,7 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only, inherits):
if inherits:
bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
bbpath = str(self.tinfoil.config_data.getVar('BBPATH', True))
for classname in inherits:
classfile = 'classes/%s.bbclass' % classname
if not bb.utils.which(bbpath, classfile, history=False):
@@ -120,13 +122,15 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
sys.exit(1)
pkg_pn = self.tinfoil.cooker.recipecaches[''].pkg_pn
(latest_versions, preferred_versions) = self.tinfoil.find_providers()
allproviders = self.tinfoil.get_all_providers()
(latest_versions, preferred_versions) = bb.providers.findProviders(self.tinfoil.config_data, self.tinfoil.cooker.recipecaches[''], pkg_pn)
allproviders = bb.providers.allProviders(self.tinfoil.cooker.recipecaches[''])
# Ensure we list skipped recipes
# We are largely guessing about PN, PV and the preferred version here,
# but we have no choice since skipped recipes are not fully parsed
skiplist = list(self.tinfoil.cooker.skiplist.keys())
skiplist.sort( key=lambda fileitem: self.tinfoil.cooker.collection.calc_bbfile_priority(fileitem) )
skiplist.reverse()
for fn in skiplist:
recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
p = recipe_parts[0]
@@ -154,19 +158,14 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
logger.plain("%s:", pn)
logger.plain(" %s %s%s", layer.ljust(20), ver, skipped)
global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
global_inherit = (self.tinfoil.config_data.getVar('INHERIT', True) or "").split()
cls_re = re.compile('classes/')
preffiles = []
items_listed = False
for p in sorted(pkg_pn):
if pnspec:
found=False
for pnm in pnspec:
if fnmatch.fnmatch(p, pnm):
found=True
break
if not found:
if not fnmatch.fnmatch(p, pnspec):
continue
if len(allproviders[p]) > 1 or not show_multi_provider_only:
@@ -247,28 +246,17 @@ skipped recipes will also be listed, with a " (skipped)" suffix.
Lists recipes with the bbappends that apply to them as subitems.
"""
if args.pnspec:
logger.plain('=== Matched appended recipes ===')
else:
logger.plain('=== Appended recipes ===')
logger.plain('=== Appended recipes ===')
pnlist = list(self.tinfoil.cooker_data.pkg_pn.keys())
pnlist.sort()
appends = False
for pn in pnlist:
if args.pnspec:
found=False
for pnm in args.pnspec:
if fnmatch.fnmatch(pn, pnm):
found=True
break
if not found:
continue
if self.show_appends_for_pn(pn):
appends = True
if not args.pnspec and self.show_appends_for_skipped():
if self.show_appends_for_skipped():
appends = True
if not appends:
@@ -277,7 +265,10 @@ Lists recipes with the bbappends that apply to them as subitems.
def show_appends_for_pn(self, pn):
filenames = self.tinfoil.cooker_data.pkg_pn[pn]
best = self.tinfoil.find_best_provider(pn)
best = bb.providers.findBestProvider(pn,
self.tinfoil.config_data,
self.tinfoil.cooker_data,
self.tinfoil.cooker_data.pkg_pn)
best_filename = os.path.basename(best[3])
return self.show_appends_output(filenames, best_filename)
@@ -328,12 +319,12 @@ NOTE: .bbappend files can impact the dependencies.
ignore_layers = (args.ignore or '').split(',')
pkg_fn = self.tinfoil.cooker_data.pkg_fn
bbpath = str(self.tinfoil.config_data.getVar('BBPATH'))
bbpath = str(self.tinfoil.config_data.getVar('BBPATH', True))
self.require_re = re.compile(r"require\s+(.+)")
self.include_re = re.compile(r"include\s+(.+)")
self.inherit_re = re.compile(r"inherit\s+(.+)")
global_inherit = (self.tinfoil.config_data.getVar('INHERIT') or "").split()
global_inherit = (self.tinfoil.config_data.getVar('INHERIT', True) or "").split()
# The bb's DEPENDS and RDEPENDS
for f in pkg_fn:
@@ -345,7 +336,10 @@ NOTE: .bbappend files can impact the dependencies.
deps = self.tinfoil.cooker_data.deps[f]
for pn in deps:
if pn in self.tinfoil.cooker_data.pkg_pn:
best = self.tinfoil.find_best_provider(pn)
best = bb.providers.findBestProvider(pn,
self.tinfoil.config_data,
self.tinfoil.cooker_data,
self.tinfoil.cooker_data.pkg_pn)
self.check_cross_depends("DEPENDS", layername, f, best[3], args.filenames, ignore_layers)
# The RDPENDS
@@ -358,11 +352,14 @@ NOTE: .bbappend files can impact the dependencies.
sorted_rdeps[k2] = 1
all_rdeps = sorted_rdeps.keys()
for rdep in all_rdeps:
all_p, best = self.tinfoil.get_runtime_providers(rdep)
all_p = bb.providers.getRuntimeProviders(self.tinfoil.cooker_data, rdep)
if all_p:
if f in all_p:
# The recipe provides this one itself, ignore
continue
best = bb.providers.filterProvidersRunTime(all_p, rdep,
self.tinfoil.config_data,
self.tinfoil.cooker_data)[0][0]
self.check_cross_depends("RDEPENDS", layername, f, best, args.filenames, ignore_layers)
# The RRECOMMENDS
@@ -375,11 +372,14 @@ NOTE: .bbappend files can impact the dependencies.
sorted_rrecs[k2] = 1
all_rrecs = sorted_rrecs.keys()
for rrec in all_rrecs:
all_p, best = self.tinfoil.get_runtime_providers(rrec)
all_p = bb.providers.getRuntimeProviders(self.tinfoil.cooker_data, rrec)
if all_p:
if f in all_p:
# The recipe provides this one itself, ignore
continue
best = bb.providers.filterProvidersRunTime(all_p, rrec,
self.tinfoil.config_data,
self.tinfoil.cooker_data)[0][0]
self.check_cross_depends("RRECOMMENDS", layername, f, best, args.filenames, ignore_layers)
# The inherit class
@@ -490,11 +490,10 @@ NOTE: .bbappend files can impact the dependencies.
parser_show_recipes = self.add_command(sp, 'show-recipes', self.do_show_recipes)
parser_show_recipes.add_argument('-f', '--filenames', help='instead of the default formatting, list filenames of higher priority recipes with the ones they overlay indented underneath', action='store_true')
parser_show_recipes.add_argument('-m', '--multiple', help='only list where multiple recipes (in the same layer or different layers) exist for the same recipe name', action='store_true')
parser_show_recipes.add_argument('-i', '--inherits', help='only list recipes that inherit the named class(es) - separate multiple classes using , (without spaces)', metavar='CLASS', default='')
parser_show_recipes.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
parser_show_recipes.add_argument('-i', '--inherits', help='only list recipes that inherit the named class', metavar='CLASS', default='')
parser_show_recipes.add_argument('pnspec', nargs='?', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
parser_show_appends = self.add_command(sp, 'show-appends', self.do_show_appends)
parser_show_appends.add_argument('pnspec', nargs='*', help='optional recipe name specification (wildcards allowed, enclose in quotes to avoid shell expansion)')
self.add_command(sp, 'show-appends', self.do_show_appends)
parser_show_cross_depends = self.add_command(sp, 'show-cross-depends', self.do_show_cross_depends)
parser_show_cross_depends.add_argument('-f', '--filenames', help='show full file path', action='store_true')

View File

@@ -15,14 +15,7 @@ from bs4.element import (
whitespace_re,
)
import html5lib
try:
# html5lib >= 0.99999999/1.0b9
from html5lib.treebuilders import base as treebuildersbase
except ImportError:
# html5lib <= 0.9999999/1.0b8
from html5lib.treebuilders import _base as treebuildersbase
from html5lib.constants import namespaces
from bs4.element import (
Comment,
Doctype,
@@ -74,7 +67,7 @@ class HTML5TreeBuilder(HTMLTreeBuilder):
return '<html><head></head><body>%s</body></html>' % fragment
class TreeBuilderForHtml5lib(treebuildersbase.TreeBuilder):
class TreeBuilderForHtml5lib(html5lib.treebuilders._base.TreeBuilder):
def __init__(self, soup, namespaceHTMLElements):
self.soup = soup
@@ -112,7 +105,7 @@ class TreeBuilderForHtml5lib(treebuildersbase.TreeBuilder):
return self.soup
def getFragment(self):
return treebuildersbase.TreeBuilder.getFragment(self).element
return html5lib.treebuilders._base.TreeBuilder.getFragment(self).element
class AttrList(object):
def __init__(self, element):
@@ -144,9 +137,9 @@ class AttrList(object):
return name in list(self.attrs.keys())
class Element(treebuildersbase.Node):
class Element(html5lib.treebuilders._base.Node):
def __init__(self, element, soup, namespace):
treebuildersbase.Node.__init__(self, element.name)
html5lib.treebuilders._base.Node.__init__(self, element.name)
self.element = element
self.soup = soup
self.namespace = namespace
@@ -331,7 +324,7 @@ class Element(treebuildersbase.Node):
class TextNode(Element):
def __init__(self, element, soup):
treebuildersbase.Node.__init__(self, None)
html5lib.treebuilders._base.Node.__init__(self, None)
self.element = element
self.soup = soup

View File

@@ -5,12 +5,16 @@ import threading
import queue
import socket
import io
import sqlite3
import bb.server.xmlrpcclient
try:
import sqlite3
except ImportError:
from pysqlite2 import dbapi2 as sqlite3
import bb.server.xmlrpc
import prserv
import prserv.db
import errno
import select
logger = logging.getLogger("BitBake.PRserv")
@@ -60,8 +64,6 @@ class PRServer(SimpleXMLRPCServer):
self.register_function(self.importone, "importone")
self.register_introspection_functions()
self.quitpipein, self.quitpipeout = os.pipe()
self.requestqueue = queue.Queue()
self.handlerthread = threading.Thread(target = self.process_request_thread)
self.handlerthread.daemon = False
@@ -78,14 +80,12 @@ class PRServer(SimpleXMLRPCServer):
bb.utils.set_process_name("PRServ Handler")
while not self.quitflag:
while not self.quit:
try:
(request, client_address) = self.requestqueue.get(True, 30)
except queue.Empty:
self.table.sync_if_dirty()
continue
if request is None:
continue
try:
self.finish_request(request, client_address)
self.shutdown_request(request)
@@ -105,8 +105,7 @@ class PRServer(SimpleXMLRPCServer):
def sigterm_handler(self, signum, stack):
if self.table:
self.table.sync()
self.quit()
self.requestqueue.put((None, None))
self.quit=True
def process_request(self, request, client_address):
self.requestqueue.put((request, client_address))
@@ -142,7 +141,7 @@ class PRServer(SimpleXMLRPCServer):
return self.table.importone(version, pkgarch, checksum, value)
def ping(self):
return not self.quitflag
return not self.quit
def getinfo(self):
return (self.host, self.port)
@@ -158,17 +157,12 @@ class PRServer(SimpleXMLRPCServer):
return None
def quit(self):
self.quitflag=True
os.write(self.quitpipeout, b"q")
os.close(self.quitpipeout)
self.quit=True
return
def work_forever(self,):
self.quitflag = False
# This timeout applies to the poll in TCPServer, we need the select
# below to wake on our quit pipe closing. We only ever call into handle_request
# if there is data there.
self.timeout = 0.01
self.quit = False
self.timeout = 0.5
bb.utils.set_process_name("PRServ")
@@ -180,17 +174,12 @@ class PRServer(SimpleXMLRPCServer):
(self.dbfile, self.host, self.port, str(os.getpid())))
self.handlerthread.start()
while not self.quitflag:
ready = select.select([self.fileno(), self.quitpipein], [], [], 30)
if self.quitflag:
break
if self.fileno() in ready[0]:
self.handle_request()
while not self.quit:
self.handle_request()
self.handlerthread.join()
self.db.disconnect()
logger.info("PRServer: stopping...")
self.server_close()
os.close(self.quitpipein)
return
def start(self):
@@ -198,7 +187,6 @@ class PRServer(SimpleXMLRPCServer):
pid = self.daemonize()
else:
pid = self.fork()
self.pid = pid
# Ensure both the parent sees this and the child from the work_forever log entry above
logger.info("Started PRServer with DBfile: %s, IP: %s, PORT: %s, PID: %s" %
@@ -254,25 +242,12 @@ class PRServer(SimpleXMLRPCServer):
sys.stdout.flush()
sys.stderr.flush()
# We could be called from a python thread with io.StringIO as
# stdout/stderr or it could be 'real' unix fd forking where we need
# to physically close the fds to prevent the program launching us from
# potentially hanging on a pipe. Handle both cases.
si = open('/dev/null', 'r')
try:
os.dup2(si.fileno(),sys.stdin.fileno())
except (AttributeError, io.UnsupportedOperation):
sys.stdin = si
so = open(self.logfile, 'a+')
try:
os.dup2(so.fileno(),sys.stdout.fileno())
except (AttributeError, io.UnsupportedOperation):
sys.stdout = so
try:
os.dup2(so.fileno(),sys.stderr.fileno())
except (AttributeError, io.UnsupportedOperation):
sys.stderr = so
se = so
os.dup2(si.fileno(),sys.stdin.fileno())
os.dup2(so.fileno(),sys.stdout.fileno())
os.dup2(se.fileno(),sys.stderr.fileno())
# Clear out all log handlers prior to the fork() to avoid calling
# event handlers not part of the PRserver
@@ -317,7 +292,7 @@ class PRServerConnection(object):
host, port = singleton.getinfo()
self.host = host
self.port = port
self.connection, self.transport = bb.server.xmlrpcclient._create_server(self.host, self.port)
self.connection, self.transport = bb.server.xmlrpc._create_server(self.host, self.port)
def terminate(self):
try:
@@ -445,10 +420,7 @@ class PRServiceConfigError(Exception):
def auto_start(d):
global singleton
# Shutdown any existing PR Server
auto_shutdown()
host_params = list(filter(None, (d.getVar('PRSERV_HOST') or '').split(':')))
host_params = list(filter(None, (d.getVar('PRSERV_HOST', True) or '').split(':')))
if not host_params:
return None
@@ -459,7 +431,7 @@ def auto_start(d):
if is_local_special(host_params[0], int(host_params[1])) and not singleton:
import bb.utils
cachedir = (d.getVar("PERSISTENT_DIR") or d.getVar("CACHE"))
cachedir = (d.getVar("PERSISTENT_DIR", True) or d.getVar("CACHE", True))
if not cachedir:
logger.critical("Please set the 'PERSISTENT_DIR' or 'CACHE' variable")
raise PRServiceConfigError
@@ -484,7 +456,7 @@ def auto_start(d):
logger.critical("PRservice %s:%d not available" % (host, port))
raise PRServiceConfigError
def auto_shutdown():
def auto_shutdown(d=None):
global singleton
if singleton:
host, port = singleton.getinfo()
@@ -492,11 +464,6 @@ def auto_shutdown():
PRServerConnection(host, port).terminate()
except:
logger.critical("Stop PRService %s:%d failed" % (host,port))
try:
os.waitpid(singleton.prserv.pid, 0)
except ChildProcessError:
pass
singleton = None
def ping(host, port):

View File

@@ -1,22 +0,0 @@
Copyright (c) 2008 - 2013 Paul Butler and contributors
This sofware may be used under a zlib/libpng-style license:
This software is provided 'as-is', without any express or implied warranty. In
no event will the authors be held liable for any damages arising from the use
of this software.
Permission is granted to anyone to use this software for any purpose, including
commercial applications, and to alter it and redistribute it freely, subject to
the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim
that you wrote the original software. If you use this software in a product, an
acknowledgment in the product documentation would be appreciated but is not
required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@@ -1,198 +0,0 @@
'''
Simple Diff for Python version 1.0
Annotate two versions of a list with the values that have been
changed between the versions, similar to unix's `diff` but with
a dead-simple Python interface.
(C) Paul Butler 2008-2012 <http://www.paulbutler.org/>
May be used and distributed under the zlib/libpng license
<http://www.opensource.org/licenses/zlib-license.php>
'''
__all__ = ['diff', 'string_diff', 'html_diff']
__version__ = '1.0'
def diff(old, new):
'''
Find the differences between two lists. Returns a list of pairs, where the
first value is in ['+','-','='] and represents an insertion, deletion, or
no change for that list. The second value of the pair is the list
of elements.
Params:
old the old list of immutable, comparable values (ie. a list
of strings)
new the new list of immutable, comparable values
Returns:
A list of pairs, with the first part of the pair being one of three
strings ('-', '+', '=') and the second part being a list of values from
the original old and/or new lists. The first part of the pair
corresponds to whether the list of values is a deletion, insertion, or
unchanged, respectively.
Examples:
>>> diff([1,2,3,4],[1,3,4])
[('=', [1]), ('-', [2]), ('=', [3, 4])]
>>> diff([1,2,3,4],[2,3,4,1])
[('-', [1]), ('=', [2, 3, 4]), ('+', [1])]
>>> diff('The quick brown fox jumps over the lazy dog'.split(),
... 'The slow blue cheese drips over the lazy carrot'.split())
... # doctest: +NORMALIZE_WHITESPACE
[('=', ['The']),
('-', ['quick', 'brown', 'fox', 'jumps']),
('+', ['slow', 'blue', 'cheese', 'drips']),
('=', ['over', 'the', 'lazy']),
('-', ['dog']),
('+', ['carrot'])]
'''
# Create a map from old values to their indices
old_index_map = dict()
for i, val in enumerate(old):
old_index_map.setdefault(val,list()).append(i)
# Find the largest substring common to old and new.
# We use a dynamic programming approach here.
#
# We iterate over each value in the `new` list, calling the
# index `inew`. At each iteration, `overlap[i]` is the
# length of the largest suffix of `old[:i]` equal to a suffix
# of `new[:inew]` (or unset when `old[i]` != `new[inew]`).
#
# At each stage of iteration, the new `overlap` (called
# `_overlap` until the original `overlap` is no longer needed)
# is built from the old one.
#
# If the length of overlap exceeds the largest substring
# seen so far (`sub_length`), we update the largest substring
# to the overlapping strings.
overlap = dict()
# `sub_start_old` is the index of the beginning of the largest overlapping
# substring in the old list. `sub_start_new` is the index of the beginning
# of the same substring in the new list. `sub_length` is the length that
# overlaps in both.
# These track the largest overlapping substring seen so far, so naturally
# we start with a 0-length substring.
sub_start_old = 0
sub_start_new = 0
sub_length = 0
for inew, val in enumerate(new):
_overlap = dict()
for iold in old_index_map.get(val,list()):
# now we are considering all values of iold such that
# `old[iold] == new[inew]`.
_overlap[iold] = (iold and overlap.get(iold - 1, 0)) + 1
if(_overlap[iold] > sub_length):
# this is the largest substring seen so far, so store its
# indices
sub_length = _overlap[iold]
sub_start_old = iold - sub_length + 1
sub_start_new = inew - sub_length + 1
overlap = _overlap
if sub_length == 0:
# If no common substring is found, we return an insert and delete...
return (old and [('-', old)] or []) + (new and [('+', new)] or [])
else:
# ...otherwise, the common substring is unchanged and we recursively
# diff the text before and after that substring
return diff(old[ : sub_start_old], new[ : sub_start_new]) + \
[('=', new[sub_start_new : sub_start_new + sub_length])] + \
diff(old[sub_start_old + sub_length : ],
new[sub_start_new + sub_length : ])
def string_diff(old, new):
'''
Returns the difference between the old and new strings when split on
whitespace. Considers punctuation a part of the word
This function is intended as an example; you'll probably want
a more sophisticated wrapper in practice.
Params:
old the old string
new the new string
Returns:
the output of `diff` on the two strings after splitting them
on whitespace (a list of change instructions; see the docstring
of `diff`)
Examples:
>>> string_diff('The quick brown fox', 'The fast blue fox')
... # doctest: +NORMALIZE_WHITESPACE
[('=', ['The']),
('-', ['quick', 'brown']),
('+', ['fast', 'blue']),
('=', ['fox'])]
'''
return diff(old.split(), new.split())
def html_diff(old, new):
'''
Returns the difference between two strings (as in stringDiff) in
HTML format. HTML code in the strings is NOT escaped, so you
will get weird results if the strings contain HTML.
This function is intended as an example; you'll probably want
a more sophisticated wrapper in practice.
Params:
old the old string
new the new string
Returns:
the output of the diff expressed with HTML <ins> and <del>
tags.
Examples:
>>> html_diff('The quick brown fox', 'The fast blue fox')
'The <del>quick brown</del> <ins>fast blue</ins> fox'
'''
con = {'=': (lambda x: x),
'+': (lambda x: "<ins>" + x + "</ins>"),
'-': (lambda x: "<del>" + x + "</del>")}
return " ".join([(con[a])(" ".join(b)) for a, b in string_diff(old, new)])
def check_diff(old, new):
'''
This tests that diffs returned by `diff` are valid. You probably won't
want to use this function, but it's provided for documentation and
testing.
A diff should satisfy the property that the old input is equal to the
elements of the result annotated with '-' or '=' concatenated together.
Likewise, the new input is equal to the elements of the result annotated
with '+' or '=' concatenated together. This function compares `old`,
`new`, and the results of `diff(old, new)` to ensure this is true.
Tests:
>>> check_diff('ABCBA', 'CBABA')
>>> check_diff('Foobarbaz', 'Foobarbaz')
>>> check_diff('Foobarbaz', 'Boobazbam')
>>> check_diff('The quick brown fox', 'Some quick brown car')
>>> check_diff('A thick red book', 'A quick blue book')
>>> check_diff('dafhjkdashfkhasfjsdafdasfsda', 'asdfaskjfhksahkfjsdha')
>>> check_diff('88288822828828288282828', '88288882882828282882828')
>>> check_diff('1234567890', '24689')
'''
old = list(old)
new = list(new)
result = diff(old, new)
_old = [val for (a, vals) in result if (a in '=-') for val in vals]
assert old == _old, 'Expected %s, got %s' % (old, _old)
_new = [val for (a, vals) in result if (a in '=+') for val in vals]
assert new == _new, 'Expected %s, got %s' % (new, _new)

View File

@@ -1,7 +1,7 @@
#
# BitBake Toaster Implementation
#
# Copyright (C) 2014-2017 Intel Corporation
# Copyright (C) 2014 Intel Corporation
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -17,11 +17,9 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from django.conf.urls import include, url
from django.conf.urls import patterns, include, url
import bldcollector.views
urlpatterns = [
urlpatterns = patterns('bldcollector.views',
# landing point for pushing a bitbake_eventlog.json file to this toaster instace
url(r'^eventfile$', bldcollector.views.eventfile, name='eventfile'),
]
url(r'^eventfile$', 'eventfile', name='eventfile'),
)

View File

@@ -37,8 +37,8 @@ class BitbakeController(object):
"""
def __init__(self, be):
import bb.server.xmlrpcclient
self.connection = bb.server.xmlrpcclient._create_server(be.bbaddress,
import bb.server.xmlrpc
self.connection = bb.server.xmlrpc._create_server(be.bbaddress,
int(be.bbport))[0]
def _runCommand(self, command):

Some files were not shown because too many files have changed in this diff Show More