mirror of
https://git.yoctoproject.org/poky
synced 2026-02-03 15:28:42 +01:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e392026ff | ||
|
|
41136dd0cf | ||
|
|
80baa2d1fb |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -8,7 +8,6 @@ pstage/
|
||||
scripts/oe-git-proxy-socks
|
||||
sources/
|
||||
meta-*/
|
||||
buildtools/
|
||||
!meta-skeleton
|
||||
!meta-selftest
|
||||
hob-image-*.bb
|
||||
@@ -30,10 +29,4 @@ hob-image-*.bb
|
||||
pull-*/
|
||||
bitbake/lib/toaster/contrib/tts/backlog.txt
|
||||
bitbake/lib/toaster/contrib/tts/log/*
|
||||
bitbake/lib/toaster/contrib/tts/.cache/*
|
||||
bitbake/lib/bb/tests/runqueue-tests/bitbake-cookerdaemon.log
|
||||
_toaster_clones/
|
||||
downloads/
|
||||
sstate-cache/
|
||||
toaster.sqlite
|
||||
.vscode/
|
||||
bitbake/lib/toaster/contrib/tts/.cache/*
|
||||
@@ -1,2 +1,2 @@
|
||||
# Template settings
|
||||
TEMPLATECONF=${TEMPLATECONF:-meta-poky/conf/templates/default}
|
||||
TEMPLATECONF=${TEMPLATECONF:-meta-poky/conf}
|
||||
|
||||
24
LICENSE
24
LICENSE
@@ -1,20 +1,14 @@
|
||||
Different components of OpenEmbedded are under different licenses (a mix
|
||||
of MIT and GPLv2). See LICENSE.GPL-2.0-only and LICENSE.MIT for further
|
||||
details of the individual licenses.
|
||||
of MIT and GPLv2). Please see:
|
||||
|
||||
meta/COPYING.GPLv2 (GPLv2)
|
||||
meta/COPYING.MIT (MIT)
|
||||
meta-selftest/COPYING.MIT (MIT)
|
||||
meta-skeleton/COPYING.MIT (MIT)
|
||||
|
||||
All metadata is MIT licensed unless otherwise stated. Source code
|
||||
included in tree for individual recipes (e.g. patches) are under
|
||||
the LICENSE stated in the associated recipe (.bb file) unless
|
||||
otherwise stated.
|
||||
included in tree for individual recipes is under the LICENSE stated in
|
||||
the associated recipe (.bb file) unless otherwise stated.
|
||||
|
||||
License information for any other files is either explicitly stated
|
||||
or defaults to GPL version 2 only.
|
||||
|
||||
Individual files contain the following style tags instead of the full license
|
||||
text to identify their license:
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
or defaults to GPL version 2.
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Note:
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
25
LICENSE.MIT
25
LICENSE.MIT
@@ -1,25 +0,0 @@
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Note:
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
@@ -1,71 +0,0 @@
|
||||
OpenEmbedded-Core and Yocto Project Maintainer Information
|
||||
==========================================================
|
||||
|
||||
OpenEmbedded and Yocto Project work jointly together to maintain the metadata,
|
||||
layers, tools and sub-projects that make up their ecosystems.
|
||||
|
||||
The projects operate through collaborative development. This currently takes
|
||||
place on mailing lists for many components as the "pull request on github"
|
||||
workflow works well for single or small numbers of maintainers but we have
|
||||
a large number, all with different specialisms and benefit from the mailing
|
||||
list review process. Changes therefore undergo peer review through mailing
|
||||
lists in many cases.
|
||||
|
||||
This file aims to acknowledge people with specific skills/knowledge/interest
|
||||
both to recognise their contributions but also empower them to help lead and
|
||||
curate those components. Where we have people with specialist knowledge in
|
||||
particular areas, during review patches/feedback from these people in these
|
||||
areas would generally carry weight.
|
||||
|
||||
This file is maintained in OE-Core but may refer to components that are separate
|
||||
to it if that makes sense in the context of maintainership. The README of specific
|
||||
layers and components should ultimately be definitive about the patch process and
|
||||
maintainership for the component.
|
||||
|
||||
Recipe Maintainers
|
||||
------------------
|
||||
|
||||
See meta/conf/distro/include/maintainers.inc
|
||||
|
||||
Component/Subsystem Maintainers
|
||||
-------------------------------
|
||||
|
||||
* Kernel (inc. linux-yocto, perf): Bruce Ashfield
|
||||
* Reproducible Builds: Joshua Watt
|
||||
* Toaster: David Reyna
|
||||
* Hash-Equivalence: Joshua Watt
|
||||
* Recipe upgrade infrastructure: Alex Kanavin
|
||||
* Toolchain: Khem Raj
|
||||
* ptest-runner: Aníbal Limón
|
||||
* opkg: Alex Stewart
|
||||
* devtool: Saul Wold
|
||||
* eSDK: Saul Wold
|
||||
* overlayfs: Vyacheslav Yurkov
|
||||
* Patchtest: Trevor Gamblin
|
||||
|
||||
Maintainers needed
|
||||
------------------
|
||||
|
||||
* Pseudo
|
||||
* Layer Index
|
||||
* recipetool
|
||||
* QA framework/automated testing
|
||||
* error reporting system/web UI
|
||||
* wic
|
||||
* Patchwork
|
||||
* Matchbox
|
||||
* Sato
|
||||
* Autobuilder
|
||||
|
||||
Layer Maintainers needed
|
||||
------------------------
|
||||
|
||||
* meta-gplv2 (ideally new strategy but active maintainer welcome)
|
||||
|
||||
Shadow maintainers/development needed
|
||||
--------------------------------------
|
||||
|
||||
* toaster
|
||||
* bitbake
|
||||
|
||||
|
||||
5
MEMORIAM
5
MEMORIAM
@@ -1,5 +0,0 @@
|
||||
Some project contributors who are sadly no longer with us:
|
||||
|
||||
Greg Gilbert (treke) - Ahead of his time with licensing
|
||||
Thomas Wood (thos) - Creator of the original sato
|
||||
Scott Rifenbark (scottrif) - Our long standing techwriter whose words live on
|
||||
26
README.LSB
Normal file
26
README.LSB
Normal file
@@ -0,0 +1,26 @@
|
||||
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.
|
||||
29
README.OE-Core
Normal file
29
README.OE-Core
Normal file
@@ -0,0 +1,29 @@
|
||||
OpenEmbedded-Core
|
||||
=================
|
||||
|
||||
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/
|
||||
|
||||
The Yocto Project has extensive documentation about OE including a reference manual
|
||||
which can be found at:
|
||||
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.
|
||||
|
||||
Mailing list:
|
||||
|
||||
http://lists.openembedded.org/mailman/listinfo/openembedded-core
|
||||
|
||||
Source code:
|
||||
|
||||
http://git.openembedded.org/openembedded-core/
|
||||
@@ -1,33 +0,0 @@
|
||||
OpenEmbedded-Core
|
||||
=================
|
||||
|
||||
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:
|
||||
https://www.openembedded.org/
|
||||
|
||||
The Yocto Project has extensive documentation about OE including a reference manual
|
||||
which can be found at:
|
||||
https://docs.yoctoproject.org/
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Please refer to our contributor guide here: https://docs.yoctoproject.org/dev/contributor-guide/
|
||||
for full details on how to submit changes.
|
||||
|
||||
As a quick guide, patches should be sent to openembedded-core@lists.openembedded.org
|
||||
The git command to do that would be:
|
||||
|
||||
git send-email -M -1 --to openembedded-core@lists.openembedded.org
|
||||
|
||||
Mailing list:
|
||||
|
||||
https://lists.openembedded.org/g/openembedded-core
|
||||
|
||||
Source code:
|
||||
|
||||
https://git.openembedded.org/openembedded-core/
|
||||
1
README.hardware
Symbolic link
1
README.hardware
Symbolic link
@@ -0,0 +1 @@
|
||||
meta-yocto-bsp/README.hardware
|
||||
@@ -1 +0,0 @@
|
||||
meta-yocto-bsp/README.hardware.md
|
||||
1
README.poky
Symbolic link
1
README.poky
Symbolic link
@@ -0,0 +1 @@
|
||||
meta-poky/README.poky
|
||||
@@ -1 +0,0 @@
|
||||
meta-poky/README.poky.md
|
||||
22
SECURITY.md
22
SECURITY.md
@@ -1,22 +0,0 @@
|
||||
How to Report a Potential Vulnerability?
|
||||
========================================
|
||||
|
||||
If you would like to report a public issue (for example, one with a released
|
||||
CVE number), please report it using the
|
||||
[https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security Security Bugzilla]
|
||||
|
||||
If you are dealing with a not-yet released or urgent issue, please send a
|
||||
message to security AT yoctoproject DOT org, including as many details as
|
||||
possible: the layer or software module affected, the recipe and its version,
|
||||
and any example code, if available.
|
||||
|
||||
Branches maintained with security fixes
|
||||
---------------------------------------
|
||||
|
||||
See [https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS Stable release and LTS]
|
||||
for detailed info regarding the policies and maintenance of Stable branches.
|
||||
|
||||
The [https://wiki.yoctoproject.org/wiki/Releases Release page] contains a list of all
|
||||
releases of the Yocto Project. Versions in grey are no longer actively maintained with
|
||||
security patches, but well-tested patches may still be accepted for them for
|
||||
significant issues.
|
||||
339
bitbake/COPYING
Normal file
339
bitbake/COPYING
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
19
bitbake/HEADER
Normal file
19
bitbake/HEADER
Normal file
@@ -0,0 +1,19 @@
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# <one line to give the program's name and a brief idea of what it does.>
|
||||
# Copyright (C) <year> <name of author>
|
||||
#
|
||||
# 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.
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
BitBake is licensed under the GNU General Public License version 2.0. See
|
||||
LICENSE.GPL-2.0-only for further details.
|
||||
|
||||
Individual files contain the following style tags instead of the full license text:
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
|
||||
BitBake is licensed under the GNU General Public License version 2.0. See COPYING for further details.
|
||||
|
||||
The following external components are distributed with this software:
|
||||
|
||||
@@ -26,4 +17,3 @@ Foundation and individual contributors.
|
||||
* Font Awesome fonts redistributed under the SIL Open Font License 1.1
|
||||
|
||||
* simplediff is distributed under the zlib license.
|
||||
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Note:
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
@@ -1,25 +0,0 @@
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
Note:
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
@@ -7,57 +7,29 @@ One of BitBake's main users, OpenEmbedded, takes this core and builds embedded L
|
||||
stacks using a task-oriented approach.
|
||||
|
||||
For information about Bitbake, see the OpenEmbedded website:
|
||||
https://www.openembedded.org/
|
||||
http://www.openembedded.org/
|
||||
|
||||
Bitbake plain documentation can be found under the doc directory or its integrated
|
||||
html version at the Yocto Project website:
|
||||
https://docs.yoctoproject.org
|
||||
|
||||
Bitbake requires Python version 3.8 or newer.
|
||||
http://yoctoproject.org/documentation
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Please refer to our contributor guide here: https://docs.yoctoproject.org/contributor-guide/
|
||||
for full details on how to submit changes.
|
||||
|
||||
As a quick guide, patches should be sent to bitbake-devel@lists.openembedded.org
|
||||
The git command to do that would be:
|
||||
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
|
||||
|
||||
If you're sending a patch related to the BitBake manual, make sure you copy
|
||||
the Yocto Project documentation mailing list:
|
||||
|
||||
git send-email -M -1 --to bitbake-devel@lists.openembedded.org --cc docs@lists.yoctoproject.org
|
||||
|
||||
Mailing list:
|
||||
|
||||
https://lists.openembedded.org/g/bitbake-devel
|
||||
http://lists.openembedded.org/mailman/listinfo/bitbake-devel
|
||||
|
||||
Source code:
|
||||
|
||||
https://git.openembedded.org/bitbake/
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Bitbake has a testsuite located in lib/bb/tests/ whichs aim to try and prevent regressions.
|
||||
You can run this with "bitbake-selftest". In particular the fetcher is well covered since
|
||||
it has so many corner cases. The datastore has many tests too. Testing with the testsuite is
|
||||
recommended before submitting patches, particularly to the fetcher and datastore. We also
|
||||
appreciate new test cases and may require them for more obscure issues.
|
||||
|
||||
To run the tests "zstd" and "git" must be installed.
|
||||
|
||||
The assumption is made that this testsuite is run from an initialized OpenEmbedded build
|
||||
environment (i.e. `source oe-init-build-env` is used). If this is not the case, run the
|
||||
testsuite as follows:
|
||||
|
||||
export PATH=$(pwd)/bin:$PATH
|
||||
bin/bitbake-selftest
|
||||
|
||||
The testsuite can alternatively be executed using pytest, e.g. obtained from PyPI (in this
|
||||
case, the PATH is configured automatically):
|
||||
|
||||
pytest
|
||||
http://git.openembedded.org/bitbake/
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
How to Report a Potential Vulnerability?
|
||||
========================================
|
||||
|
||||
If you would like to report a public issue (for example, one with a released
|
||||
CVE number), please report it using the
|
||||
[https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Security Security Bugzilla].
|
||||
If you have a patch ready, submit it following the same procedure as any other
|
||||
patch as described in README.md.
|
||||
|
||||
If you are dealing with a not-yet released or urgent issue, please send a
|
||||
message to security AT yoctoproject DOT org, including as many details as
|
||||
possible: the layer or software module affected, the recipe and its version,
|
||||
and any example code, if available.
|
||||
|
||||
Branches maintained with security fixes
|
||||
---------------------------------------
|
||||
|
||||
See [https://wiki.yoctoproject.org/wiki/Stable_Release_and_LTS Stable release and LTS]
|
||||
for detailed info regarding the policies and maintenance of Stable branches.
|
||||
|
||||
The [https://wiki.yoctoproject.org/wiki/Releases Release page] contains a list of all
|
||||
releases of the Yocto Project. Versions in grey are no longer actively maintained with
|
||||
security patches, but well-tested patches may still be accepted for them for
|
||||
significant issues.
|
||||
@@ -1,4 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (C) 2003, 2004 Chris Larson
|
||||
# Copyright (C) 2003, 2004 Phil Blundell
|
||||
@@ -7,13 +9,21 @@
|
||||
# Copyright (C) 2005 ROAD GmbH
|
||||
# Copyright (C) 2006 Richard Purdie
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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 warnings
|
||||
warnings.simplefilter("default")
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||
'lib'))
|
||||
@@ -25,9 +35,10 @@ except RuntimeError as exc:
|
||||
from bb import cookerdata
|
||||
from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException
|
||||
|
||||
bb.utils.check_system_locale()
|
||||
if sys.getfilesystemencoding() != "utf-8":
|
||||
sys.exit("Please use a locale setting which supports UTF-8 (such as LANG=en_US.UTF-8).\nPython can't change the filesystem locale after loading so we need a UTF-8 when Python starts or things won't work.")
|
||||
|
||||
__version__ = "2.9.1"
|
||||
__version__ = "1.42.0"
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __version__ != bb.__version__:
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
#
|
||||
# Copyright (C) 2012-2013, 2017 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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 warnings
|
||||
|
||||
warnings.simplefilter("default")
|
||||
import argparse
|
||||
import logging
|
||||
import pickle
|
||||
@@ -28,7 +36,6 @@ logger = bb.msg.logger_create(myname)
|
||||
|
||||
is_dump = myname == 'bitbake-dumpsig'
|
||||
|
||||
|
||||
def find_siginfo(tinfoil, pn, taskname, sigs=None):
|
||||
result = None
|
||||
tinfoil.set_event_mask(['bb.event.FindSigInfoResult',
|
||||
@@ -54,7 +61,6 @@ def find_siginfo(tinfoil, pn, taskname, sigs=None):
|
||||
sys.exit(2)
|
||||
return result
|
||||
|
||||
|
||||
def find_siginfo_task(bbhandler, pn, taskname, sig1=None, sig2=None):
|
||||
""" Find the most recent signature files for the specified PN/task """
|
||||
|
||||
@@ -63,26 +69,22 @@ def find_siginfo_task(bbhandler, pn, taskname, sig1=None, sig2=None):
|
||||
|
||||
if sig1 and sig2:
|
||||
sigfiles = find_siginfo(bbhandler, pn, taskname, [sig1, sig2])
|
||||
if not sigfiles:
|
||||
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 sig1 not in sigfiles:
|
||||
elif not sig1 in sigfiles:
|
||||
logger.error('No sigdata files found matching %s %s with signature %s' % (pn, taskname, sig1))
|
||||
sys.exit(1)
|
||||
elif sig2 not in sigfiles:
|
||||
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]['path'], sigfiles[sig2]['path']]
|
||||
latestfiles = [sigfiles[sig1], sigfiles[sig2]]
|
||||
else:
|
||||
sigfiles = find_siginfo(bbhandler, pn, taskname)
|
||||
latestsigs = sorted(sigfiles.keys(), key=lambda h: sigfiles[h]['time'])[-2:]
|
||||
if not latestsigs:
|
||||
filedates = find_siginfo(bbhandler, pn, taskname)
|
||||
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-2:]
|
||||
if not latestfiles:
|
||||
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
|
||||
sys.exit(1)
|
||||
latestfiles = [sigfiles[latestsigs[0]]['path']]
|
||||
if len(latestsigs) > 1:
|
||||
latestfiles.append(sigfiles[latestsigs[1]]['path'])
|
||||
|
||||
return latestfiles
|
||||
|
||||
@@ -93,17 +95,17 @@ def recursecb(key, hash1, hash2):
|
||||
hashfiles = find_siginfo(tinfoil, key, None, hashes)
|
||||
|
||||
recout = []
|
||||
if not hashfiles:
|
||||
if len(hashfiles) == 0:
|
||||
recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
|
||||
elif hash1 not in hashfiles:
|
||||
elif not hash1 in hashfiles:
|
||||
recout.append("Unable to find matching sigdata for %s with hash %s" % (key, hash1))
|
||||
elif hash2 not in hashfiles:
|
||||
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]['path'], hashfiles[hash2]['path'], recursecb, color=color)
|
||||
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.append(' ' + line)
|
||||
|
||||
return recout
|
||||
|
||||
@@ -117,36 +119,36 @@ parser.add_argument('-D', '--debug',
|
||||
|
||||
if is_dump:
|
||||
parser.add_argument("-t", "--task",
|
||||
help="find the signature data file for the last run of the specified task",
|
||||
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
|
||||
help="find the signature data file for the last run of the specified task",
|
||||
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
|
||||
|
||||
parser.add_argument("sigdatafile1",
|
||||
help="Signature file to dump. Not used when using -t/--task.",
|
||||
action="store", nargs='?', metavar="sigdatafile")
|
||||
help="Signature file to dump. Not used when using -t/--task.",
|
||||
action="store", nargs='?', metavar="sigdatafile")
|
||||
else:
|
||||
parser.add_argument('-c', '--color',
|
||||
help='Colorize the output (where %(metavar)s is %(choices)s)',
|
||||
choices=['auto', 'always', 'never'], default='auto', metavar='color')
|
||||
help='Colorize the output (where %(metavar)s is %(choices)s)',
|
||||
choices=['auto', 'always', 'never'], default='auto', metavar='color')
|
||||
|
||||
parser.add_argument('-d', '--dump',
|
||||
help='Dump the last signature data instead of comparing (equivalent to using bitbake-dumpsig)',
|
||||
action='store_true')
|
||||
help='Dump the last signature data instead of comparing (equivalent to using bitbake-dumpsig)',
|
||||
action='store_true')
|
||||
|
||||
parser.add_argument("-t", "--task",
|
||||
help="find the signature data files for the last two runs of the specified task and compare them",
|
||||
action="store", dest="taskargs", nargs=2, metavar=('recipename', 'taskname'))
|
||||
help="find the signature data files for the 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'))
|
||||
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='?')
|
||||
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='?')
|
||||
help="Second signature file to compare",
|
||||
action="store", nargs='?')
|
||||
|
||||
options = parser.parse_args()
|
||||
if is_dump:
|
||||
@@ -164,8 +166,7 @@ if options.taskargs:
|
||||
with bb.tinfoil.Tinfoil() as tinfoil:
|
||||
tinfoil.prepare(config_only=True)
|
||||
if not options.dump and options.sigargs:
|
||||
files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0],
|
||||
options.sigargs[1])
|
||||
files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1], options.sigargs[0], options.sigargs[1])
|
||||
else:
|
||||
files = find_siginfo_task(tinfoil, options.taskargs[0], options.taskargs[1])
|
||||
|
||||
@@ -174,8 +175,7 @@ if options.taskargs:
|
||||
output = bb.siggen.dump_sigfile(files[-1])
|
||||
else:
|
||||
if len(files) < 2:
|
||||
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (
|
||||
options.taskargs[0], options.taskargs[1]))
|
||||
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (options.taskargs[0], options.taskargs[1]))
|
||||
sys.exit(1)
|
||||
|
||||
# Recurse into signature comparison
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2021 Richard Purdie
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
|
||||
bindir = os.path.dirname(__file__)
|
||||
topdir = os.path.dirname(bindir)
|
||||
sys.path[0:0] = [os.path.join(topdir, 'lib')]
|
||||
|
||||
import bb.tinfoil
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Bitbake Query Variable")
|
||||
parser.add_argument("variable", help="variable name to query")
|
||||
parser.add_argument("-r", "--recipe", help="Recipe name to query", default=None, required=False)
|
||||
parser.add_argument('-u', '--unexpand', help='Do not expand the value (with --value)', action="store_true")
|
||||
parser.add_argument('-f', '--flag', help='Specify a variable flag to query (with --value)', default=None)
|
||||
parser.add_argument('--value', help='Only report the value, no history and no variable name', action="store_true")
|
||||
parser.add_argument('-q', '--quiet', help='Silence bitbake server logging', action="store_true")
|
||||
parser.add_argument('--ignore-undefined', help='Suppress any errors related to undefined variables', action="store_true")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.value:
|
||||
if args.unexpand:
|
||||
sys.exit("--unexpand only makes sense with --value")
|
||||
|
||||
if args.flag:
|
||||
sys.exit("--flag only makes sense with --value")
|
||||
|
||||
quiet = args.quiet or args.value
|
||||
with bb.tinfoil.Tinfoil(tracking=True, setup_logging=not quiet) as tinfoil:
|
||||
if args.recipe:
|
||||
tinfoil.prepare(quiet=3 if quiet else 2)
|
||||
d = tinfoil.parse_recipe(args.recipe)
|
||||
else:
|
||||
tinfoil.prepare(quiet=2, config_only=True)
|
||||
d = tinfoil.config_data
|
||||
|
||||
value = None
|
||||
if args.flag:
|
||||
value = d.getVarFlag(args.variable, args.flag, expand=not args.unexpand)
|
||||
if value is None and not args.ignore_undefined:
|
||||
sys.exit(f"The flag '{args.flag}' is not defined for variable '{args.variable}'")
|
||||
else:
|
||||
value = d.getVar(args.variable, expand=not args.unexpand)
|
||||
if value is None and not args.ignore_undefined:
|
||||
sys.exit(f"The variable '{args.variable}' is not defined")
|
||||
if args.value:
|
||||
print(str(value if value is not None else ""))
|
||||
else:
|
||||
bb.data.emit_var(args.variable, d=d, all=True)
|
||||
@@ -1,418 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2019 Garmin Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import logging
|
||||
import os
|
||||
import pprint
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import warnings
|
||||
import netrc
|
||||
import json
|
||||
import statistics
|
||||
warnings.simplefilter("default")
|
||||
|
||||
try:
|
||||
import tqdm
|
||||
ProgressBar = tqdm.tqdm
|
||||
except ImportError:
|
||||
class ProgressBar(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
def update(self):
|
||||
pass
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
|
||||
|
||||
import hashserv
|
||||
import bb.asyncrpc
|
||||
|
||||
DEFAULT_ADDRESS = 'unix://./hashserve.sock'
|
||||
METHOD = 'stress.test.method'
|
||||
|
||||
def print_user(u):
|
||||
print(f"Username: {u['username']}")
|
||||
if "permissions" in u:
|
||||
print("Permissions: " + " ".join(u["permissions"]))
|
||||
if "token" in u:
|
||||
print(f"Token: {u['token']}")
|
||||
|
||||
|
||||
def main():
|
||||
def handle_get(args, client):
|
||||
result = client.get_taskhash(args.method, args.taskhash, all_properties=True)
|
||||
if not result:
|
||||
return 0
|
||||
|
||||
print(json.dumps(result, sort_keys=True, indent=4))
|
||||
return 0
|
||||
|
||||
def handle_get_outhash(args, client):
|
||||
result = client.get_outhash(args.method, args.outhash, args.taskhash)
|
||||
if not result:
|
||||
return 0
|
||||
|
||||
print(json.dumps(result, sort_keys=True, indent=4))
|
||||
return 0
|
||||
|
||||
def handle_stats(args, client):
|
||||
if args.reset:
|
||||
s = client.reset_stats()
|
||||
else:
|
||||
s = client.get_stats()
|
||||
print(json.dumps(s, sort_keys=True, indent=4))
|
||||
return 0
|
||||
|
||||
def handle_stress(args, client):
|
||||
def thread_main(pbar, lock):
|
||||
nonlocal found_hashes
|
||||
nonlocal missed_hashes
|
||||
nonlocal max_time
|
||||
nonlocal times
|
||||
|
||||
with hashserv.create_client(args.address) as client:
|
||||
for i in range(args.requests):
|
||||
taskhash = hashlib.sha256()
|
||||
taskhash.update(args.taskhash_seed.encode('utf-8'))
|
||||
taskhash.update(str(i).encode('utf-8'))
|
||||
|
||||
start_time = time.perf_counter()
|
||||
l = client.get_unihash(METHOD, taskhash.hexdigest())
|
||||
elapsed = time.perf_counter() - start_time
|
||||
|
||||
with lock:
|
||||
if l:
|
||||
found_hashes += 1
|
||||
else:
|
||||
missed_hashes += 1
|
||||
|
||||
times.append(elapsed)
|
||||
pbar.update()
|
||||
|
||||
max_time = 0
|
||||
found_hashes = 0
|
||||
missed_hashes = 0
|
||||
lock = threading.Lock()
|
||||
times = []
|
||||
start_time = time.perf_counter()
|
||||
with ProgressBar(total=args.clients * args.requests) as pbar:
|
||||
threads = [threading.Thread(target=thread_main, args=(pbar, lock), daemon=False) for _ in range(args.clients)]
|
||||
for t in threads:
|
||||
t.start()
|
||||
|
||||
for t in threads:
|
||||
t.join()
|
||||
total_elapsed = time.perf_counter() - start_time
|
||||
|
||||
with lock:
|
||||
mean = statistics.mean(times)
|
||||
median = statistics.median(times)
|
||||
stddev = statistics.pstdev(times)
|
||||
|
||||
print(f"Number of clients: {args.clients}")
|
||||
print(f"Requests per client: {args.requests}")
|
||||
print(f"Number of requests: {len(times)}")
|
||||
print(f"Total elapsed time: {total_elapsed:.3f}s")
|
||||
print(f"Total request rate: {len(times)/total_elapsed:.3f} req/s")
|
||||
print(f"Average request time: {mean:.3f}s")
|
||||
print(f"Median request time: {median:.3f}s")
|
||||
print(f"Request time std dev: {stddev:.3f}s")
|
||||
print(f"Maximum request time: {max(times):.3f}s")
|
||||
print(f"Minimum request time: {min(times):.3f}s")
|
||||
print(f"Hashes found: {found_hashes}")
|
||||
print(f"Hashes missed: {missed_hashes}")
|
||||
|
||||
if args.report:
|
||||
with ProgressBar(total=args.requests) as pbar:
|
||||
for i in range(args.requests):
|
||||
taskhash = hashlib.sha256()
|
||||
taskhash.update(args.taskhash_seed.encode('utf-8'))
|
||||
taskhash.update(str(i).encode('utf-8'))
|
||||
|
||||
outhash = hashlib.sha256()
|
||||
outhash.update(args.outhash_seed.encode('utf-8'))
|
||||
outhash.update(str(i).encode('utf-8'))
|
||||
|
||||
client.report_unihash(taskhash.hexdigest(), METHOD, outhash.hexdigest(), taskhash.hexdigest())
|
||||
|
||||
with lock:
|
||||
pbar.update()
|
||||
|
||||
def handle_remove(args, client):
|
||||
where = {k: v for k, v in args.where}
|
||||
if where:
|
||||
result = client.remove(where)
|
||||
print("Removed %d row(s)" % (result["count"]))
|
||||
else:
|
||||
print("No query specified")
|
||||
|
||||
def handle_clean_unused(args, client):
|
||||
result = client.clean_unused(args.max_age)
|
||||
print("Removed %d rows" % (result["count"]))
|
||||
return 0
|
||||
|
||||
def handle_refresh_token(args, client):
|
||||
r = client.refresh_token(args.username)
|
||||
print_user(r)
|
||||
|
||||
def handle_set_user_permissions(args, client):
|
||||
r = client.set_user_perms(args.username, args.permissions)
|
||||
print_user(r)
|
||||
|
||||
def handle_get_user(args, client):
|
||||
r = client.get_user(args.username)
|
||||
print_user(r)
|
||||
|
||||
def handle_get_all_users(args, client):
|
||||
users = client.get_all_users()
|
||||
print("{username:20}| {permissions}".format(username="Username", permissions="Permissions"))
|
||||
print(("-" * 20) + "+" + ("-" * 20))
|
||||
for u in users:
|
||||
print("{username:20}| {permissions}".format(username=u["username"], permissions=" ".join(u["permissions"])))
|
||||
|
||||
def handle_new_user(args, client):
|
||||
r = client.new_user(args.username, args.permissions)
|
||||
print_user(r)
|
||||
|
||||
def handle_delete_user(args, client):
|
||||
r = client.delete_user(args.username)
|
||||
print_user(r)
|
||||
|
||||
def handle_get_db_usage(args, client):
|
||||
usage = client.get_db_usage()
|
||||
print(usage)
|
||||
tables = sorted(usage.keys())
|
||||
print("{name:20}| {rows:20}".format(name="Table name", rows="Rows"))
|
||||
print(("-" * 20) + "+" + ("-" * 20))
|
||||
for t in tables:
|
||||
print("{name:20}| {rows:<20}".format(name=t, rows=usage[t]["rows"]))
|
||||
print()
|
||||
|
||||
total_rows = sum(t["rows"] for t in usage.values())
|
||||
print(f"Total rows: {total_rows}")
|
||||
|
||||
def handle_get_db_query_columns(args, client):
|
||||
columns = client.get_db_query_columns()
|
||||
print("\n".join(sorted(columns)))
|
||||
|
||||
def handle_gc_status(args, client):
|
||||
result = client.gc_status()
|
||||
if not result["mark"]:
|
||||
print("No Garbage collection in progress")
|
||||
return 0
|
||||
|
||||
print("Current Mark: %s" % result["mark"])
|
||||
print("Total hashes to keep: %d" % result["keep"])
|
||||
print("Total hashes to remove: %s" % result["remove"])
|
||||
return 0
|
||||
|
||||
def handle_gc_mark(args, client):
|
||||
where = {k: v for k, v in args.where}
|
||||
result = client.gc_mark(args.mark, where)
|
||||
print("New hashes marked: %d" % result["count"])
|
||||
return 0
|
||||
|
||||
def handle_gc_sweep(args, client):
|
||||
result = client.gc_sweep(args.mark)
|
||||
print("Removed %d rows" % result["count"])
|
||||
return 0
|
||||
|
||||
def handle_unihash_exists(args, client):
|
||||
result = client.unihash_exists(args.unihash)
|
||||
if args.quiet:
|
||||
return 0 if result else 1
|
||||
|
||||
print("true" if result else "false")
|
||||
return 0
|
||||
|
||||
def handle_ping(args, client):
|
||||
times = []
|
||||
for i in range(1, args.count + 1):
|
||||
if not args.quiet:
|
||||
print(f"Ping {i} of {args.count}... ", end="")
|
||||
start_time = time.perf_counter()
|
||||
client.ping()
|
||||
elapsed = time.perf_counter() - start_time
|
||||
times.append(elapsed)
|
||||
if not args.quiet:
|
||||
print(f"{elapsed:.3f}s")
|
||||
|
||||
mean = statistics.mean(times)
|
||||
median = statistics.median(times)
|
||||
std_dev = statistics.pstdev(times)
|
||||
|
||||
if not args.quiet:
|
||||
print("------------------------")
|
||||
print(f"Number of pings: {len(times)}")
|
||||
print(f"Average round trip time: {mean:.3f}s")
|
||||
print(f"Median round trip time: {median:.3f}s")
|
||||
print(f"Round trip time std dev: {std_dev:.3f}s")
|
||||
print(f"Min time is: {min(times):.3f}s")
|
||||
print(f"Max time is: {max(times):.3f}s")
|
||||
return 0
|
||||
|
||||
parser = argparse.ArgumentParser(description='Hash Equivalence Client')
|
||||
parser.add_argument('--address', default=DEFAULT_ADDRESS, help='Server address (default "%(default)s")')
|
||||
parser.add_argument('--log', default='WARNING', help='Set logging level')
|
||||
parser.add_argument('--login', '-l', metavar="USERNAME", help="Authenticate as USERNAME")
|
||||
parser.add_argument('--password', '-p', metavar="TOKEN", help="Authenticate using token TOKEN")
|
||||
parser.add_argument('--become', '-b', metavar="USERNAME", help="Impersonate user USERNAME (if allowed) when performing actions")
|
||||
parser.add_argument('--no-netrc', '-n', action="store_false", dest="netrc", help="Do not use .netrc")
|
||||
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
get_parser = subparsers.add_parser('get', help="Get the unihash for a taskhash")
|
||||
get_parser.add_argument("method", help="Method to query")
|
||||
get_parser.add_argument("taskhash", help="Task hash to query")
|
||||
get_parser.set_defaults(func=handle_get)
|
||||
|
||||
get_outhash_parser = subparsers.add_parser('get-outhash', help="Get output hash information")
|
||||
get_outhash_parser.add_argument("method", help="Method to query")
|
||||
get_outhash_parser.add_argument("outhash", help="Output hash to query")
|
||||
get_outhash_parser.add_argument("taskhash", help="Task hash to query")
|
||||
get_outhash_parser.set_defaults(func=handle_get_outhash)
|
||||
|
||||
stats_parser = subparsers.add_parser('stats', help='Show server stats')
|
||||
stats_parser.add_argument('--reset', action='store_true',
|
||||
help='Reset server stats')
|
||||
stats_parser.set_defaults(func=handle_stats)
|
||||
|
||||
stress_parser = subparsers.add_parser('stress', help='Run stress test')
|
||||
stress_parser.add_argument('--clients', type=int, default=10,
|
||||
help='Number of simultaneous clients')
|
||||
stress_parser.add_argument('--requests', type=int, default=1000,
|
||||
help='Number of requests each client will perform')
|
||||
stress_parser.add_argument('--report', action='store_true',
|
||||
help='Report new hashes')
|
||||
stress_parser.add_argument('--taskhash-seed', default='',
|
||||
help='Include string in taskhash')
|
||||
stress_parser.add_argument('--outhash-seed', default='',
|
||||
help='Include string in outhash')
|
||||
stress_parser.set_defaults(func=handle_stress)
|
||||
|
||||
remove_parser = subparsers.add_parser('remove', help="Remove hash entries")
|
||||
remove_parser.add_argument("--where", "-w", metavar="KEY VALUE", nargs=2, action="append", default=[],
|
||||
help="Remove entries from table where KEY == VALUE")
|
||||
remove_parser.set_defaults(func=handle_remove)
|
||||
|
||||
clean_unused_parser = subparsers.add_parser('clean-unused', help="Remove unused database entries")
|
||||
clean_unused_parser.add_argument("max_age", metavar="SECONDS", type=int, help="Remove unused entries older than SECONDS old")
|
||||
clean_unused_parser.set_defaults(func=handle_clean_unused)
|
||||
|
||||
refresh_token_parser = subparsers.add_parser('refresh-token', help="Refresh auth token")
|
||||
refresh_token_parser.add_argument("--username", "-u", help="Refresh the token for another user (if authorized)")
|
||||
refresh_token_parser.set_defaults(func=handle_refresh_token)
|
||||
|
||||
set_user_perms_parser = subparsers.add_parser('set-user-perms', help="Set new permissions for user")
|
||||
set_user_perms_parser.add_argument("--username", "-u", help="Username", required=True)
|
||||
set_user_perms_parser.add_argument("permissions", metavar="PERM", nargs="*", default=[], help="New permissions")
|
||||
set_user_perms_parser.set_defaults(func=handle_set_user_permissions)
|
||||
|
||||
get_user_parser = subparsers.add_parser('get-user', help="Get user")
|
||||
get_user_parser.add_argument("--username", "-u", help="Username")
|
||||
get_user_parser.set_defaults(func=handle_get_user)
|
||||
|
||||
get_all_users_parser = subparsers.add_parser('get-all-users', help="List all users")
|
||||
get_all_users_parser.set_defaults(func=handle_get_all_users)
|
||||
|
||||
new_user_parser = subparsers.add_parser('new-user', help="Create new user")
|
||||
new_user_parser.add_argument("--username", "-u", help="Username", required=True)
|
||||
new_user_parser.add_argument("permissions", metavar="PERM", nargs="*", default=[], help="New permissions")
|
||||
new_user_parser.set_defaults(func=handle_new_user)
|
||||
|
||||
delete_user_parser = subparsers.add_parser('delete-user', help="Delete user")
|
||||
delete_user_parser.add_argument("--username", "-u", help="Username", required=True)
|
||||
delete_user_parser.set_defaults(func=handle_delete_user)
|
||||
|
||||
db_usage_parser = subparsers.add_parser('get-db-usage', help="Database Usage")
|
||||
db_usage_parser.set_defaults(func=handle_get_db_usage)
|
||||
|
||||
db_query_columns_parser = subparsers.add_parser('get-db-query-columns', help="Show columns that can be used in database queries")
|
||||
db_query_columns_parser.set_defaults(func=handle_get_db_query_columns)
|
||||
|
||||
gc_status_parser = subparsers.add_parser("gc-status", help="Show garbage collection status")
|
||||
gc_status_parser.set_defaults(func=handle_gc_status)
|
||||
|
||||
gc_mark_parser = subparsers.add_parser('gc-mark', help="Mark hashes to be kept for garbage collection")
|
||||
gc_mark_parser.add_argument("mark", help="Mark for this garbage collection operation")
|
||||
gc_mark_parser.add_argument("--where", "-w", metavar="KEY VALUE", nargs=2, action="append", default=[],
|
||||
help="Keep entries in table where KEY == VALUE")
|
||||
gc_mark_parser.set_defaults(func=handle_gc_mark)
|
||||
|
||||
gc_sweep_parser = subparsers.add_parser('gc-sweep', help="Perform garbage collection and delete any entries that are not marked")
|
||||
gc_sweep_parser.add_argument("mark", help="Mark for this garbage collection operation")
|
||||
gc_sweep_parser.set_defaults(func=handle_gc_sweep)
|
||||
|
||||
unihash_exists_parser = subparsers.add_parser('unihash-exists', help="Check if a unihash is known to the server")
|
||||
unihash_exists_parser.add_argument("--quiet", action="store_true", help="Don't print status. Instead, exit with 0 if unihash exists and 1 if it does not")
|
||||
unihash_exists_parser.add_argument("unihash", help="Unihash to check")
|
||||
unihash_exists_parser.set_defaults(func=handle_unihash_exists)
|
||||
|
||||
ping_parser = subparsers.add_parser('ping', help="Ping server")
|
||||
ping_parser.add_argument("-n", "--count", type=int, help="Number of pings. Default is %(default)s", default=10)
|
||||
ping_parser.add_argument("-q", "--quiet", action="store_true", help="Don't print each ping; only print results")
|
||||
ping_parser.set_defaults(func=handle_ping)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
logger = logging.getLogger('hashserv')
|
||||
|
||||
level = getattr(logging, args.log.upper(), None)
|
||||
if not isinstance(level, int):
|
||||
raise ValueError('Invalid log level: %s' % args.log)
|
||||
|
||||
logger.setLevel(level)
|
||||
console = logging.StreamHandler()
|
||||
console.setLevel(level)
|
||||
logger.addHandler(console)
|
||||
|
||||
login = args.login
|
||||
password = args.password
|
||||
|
||||
if login is None and args.netrc:
|
||||
try:
|
||||
n = netrc.netrc()
|
||||
auth = n.authenticators(args.address)
|
||||
if auth is not None:
|
||||
login, _, password = auth
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except netrc.NetrcParseError as e:
|
||||
sys.stderr.write(f"Error parsing {e.filename}:{e.lineno}: {e.msg}\n")
|
||||
|
||||
func = getattr(args, 'func', None)
|
||||
if func:
|
||||
try:
|
||||
with hashserv.create_client(args.address, login, password) as client:
|
||||
if args.become:
|
||||
client.become_user(args.become)
|
||||
return func(args, client)
|
||||
except bb.asyncrpc.InvokeError as e:
|
||||
print(f"ERROR: {e}")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
ret = main()
|
||||
except Exception:
|
||||
ret = 1
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(ret)
|
||||
@@ -2,178 +2,66 @@
|
||||
#
|
||||
# Copyright (C) 2018 Garmin Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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 logging
|
||||
import argparse
|
||||
import sqlite3
|
||||
import warnings
|
||||
|
||||
warnings.simplefilter("default")
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib"))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),'lib'))
|
||||
|
||||
import hashserv
|
||||
from hashserv.server import DEFAULT_ANON_PERMS
|
||||
|
||||
VERSION = "1.0.0"
|
||||
|
||||
DEFAULT_BIND = "unix://./hashserve.sock"
|
||||
|
||||
DEFAULT_HOST = ''
|
||||
DEFAULT_PORT = 8686
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Hash Equivalence Reference Server. Version=%s" % VERSION,
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
epilog="""
|
||||
The bind address may take one of the following formats:
|
||||
unix://PATH - Bind to unix domain socket at PATH
|
||||
ws://ADDRESS:PORT - Bind to websocket on ADDRESS:PORT
|
||||
ADDRESS:PORT - Bind to raw TCP socket on ADDRESS:PORT
|
||||
|
||||
To bind to all addresses, leave the ADDRESS empty, e.g. "--bind :8686" or
|
||||
"--bind ws://:8686". To bind to a specific IPv6 address, enclose the address in
|
||||
"[]", e.g. "--bind [::1]:8686" or "--bind ws://[::1]:8686"
|
||||
|
||||
Note that the default Anonymous permissions are designed to not break existing
|
||||
server instances when upgrading, but are not particularly secure defaults. If
|
||||
you want to use authentication, it is recommended that you use "--anon-perms
|
||||
@read" to only give anonymous users read access, or "--anon-perms @none" to
|
||||
give un-authenticated users no access at all.
|
||||
|
||||
Setting "--anon-perms @all" or "--anon-perms @user-admin" is not allowed, since
|
||||
this would allow anonymous users to manage all users accounts, which is a bad
|
||||
idea.
|
||||
|
||||
If you are using user authentication, you should run your server in websockets
|
||||
mode with an SSL terminating load balancer in front of it (as this server does
|
||||
not implement SSL). Otherwise all usernames and passwords will be transmitted
|
||||
in the clear. When configured this way, clients can connect using a secure
|
||||
websocket, as in "wss://SERVER:PORT"
|
||||
|
||||
The following permissions are supported by the server:
|
||||
|
||||
@none - No permissions
|
||||
@read - The ability to read equivalent hashes from the server
|
||||
@report - The ability to report equivalent hashes to the server
|
||||
@db-admin - Manage the hash database(s). This includes cleaning the
|
||||
database, removing hashes, etc.
|
||||
@user-admin - The ability to manage user accounts. This includes, creating
|
||||
users, deleting users, resetting login tokens, and assigning
|
||||
permissions.
|
||||
@all - All possible permissions, including any that may be added
|
||||
in the future
|
||||
""",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-b",
|
||||
"--bind",
|
||||
default=os.environ.get("HASHSERVER_BIND", DEFAULT_BIND),
|
||||
help='Bind address (default $HASHSERVER_BIND, "%(default)s")',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--database",
|
||||
default=os.environ.get("HASHSERVER_DB", "./hashserv.db"),
|
||||
help='Database file (default $HASHSERVER_DB, "%(default)s")',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--log",
|
||||
default=os.environ.get("HASHSERVER_LOG_LEVEL", "WARNING"),
|
||||
help='Set logging level (default $HASHSERVER_LOG_LEVEL, "%(default)s")',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-u",
|
||||
"--upstream",
|
||||
default=os.environ.get("HASHSERVER_UPSTREAM", None),
|
||||
help="Upstream hashserv to pull hashes from ($HASHSERVER_UPSTREAM)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--read-only",
|
||||
action="store_true",
|
||||
help="Disallow write operations from clients ($HASHSERVER_READ_ONLY)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--db-username",
|
||||
default=os.environ.get("HASHSERVER_DB_USERNAME", None),
|
||||
help="Database username ($HASHSERVER_DB_USERNAME)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--db-password",
|
||||
default=os.environ.get("HASHSERVER_DB_PASSWORD", None),
|
||||
help="Database password ($HASHSERVER_DB_PASSWORD)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--anon-perms",
|
||||
metavar="PERM[,PERM[,...]]",
|
||||
default=os.environ.get("HASHSERVER_ANON_PERMS", ",".join(DEFAULT_ANON_PERMS)),
|
||||
help='Permissions to give anonymous users (default $HASHSERVER_ANON_PERMS, "%(default)s")',
|
||||
)
|
||||
parser.add_argument(
|
||||
"--admin-user",
|
||||
default=os.environ.get("HASHSERVER_ADMIN_USER", None),
|
||||
help="Create default admin user with name ADMIN_USER ($HASHSERVER_ADMIN_USER)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--admin-password",
|
||||
default=os.environ.get("HASHSERVER_ADMIN_PASSWORD", None),
|
||||
help="Create default admin user with password ADMIN_PASSWORD ($HASHSERVER_ADMIN_PASSWORD)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--reuseport",
|
||||
action="store_true",
|
||||
help="Enable SO_REUSEPORT, allowing multiple servers to bind to the same port for load balancing",
|
||||
)
|
||||
parser = argparse.ArgumentParser(description='HTTP Equivalence Reference Server. Version=%s' % VERSION)
|
||||
parser.add_argument('--address', default=DEFAULT_HOST, help='Bind address (default "%(default)s")')
|
||||
parser.add_argument('--port', type=int, default=DEFAULT_PORT, help='Bind port (default %(default)d)')
|
||||
parser.add_argument('--prefix', default='', help='HTTP path prefix (default "%(default)s")')
|
||||
parser.add_argument('--database', default='./hashserv.db', help='Database file (default "%(default)s")')
|
||||
parser.add_argument('--log', default='WARNING', help='Set logging level')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
logger = logging.getLogger("hashserv")
|
||||
logger = logging.getLogger('hashserv')
|
||||
|
||||
level = getattr(logging, args.log.upper(), None)
|
||||
if not isinstance(level, int):
|
||||
raise ValueError(
|
||||
"Invalid log level: %s (Try ERROR/WARNING/INFO/DEBUG)" % args.log
|
||||
)
|
||||
raise ValueError('Invalid log level: %s' % args.log)
|
||||
|
||||
logger.setLevel(level)
|
||||
console = logging.StreamHandler()
|
||||
console.setLevel(level)
|
||||
logger.addHandler(console)
|
||||
|
||||
read_only = (os.environ.get("HASHSERVER_READ_ONLY", "0") == "1") or args.read_only
|
||||
if "," in args.anon_perms:
|
||||
anon_perms = args.anon_perms.split(",")
|
||||
else:
|
||||
anon_perms = args.anon_perms.split()
|
||||
db = sqlite3.connect(args.database)
|
||||
|
||||
server = hashserv.create_server(
|
||||
args.bind,
|
||||
args.database,
|
||||
upstream=args.upstream,
|
||||
read_only=read_only,
|
||||
db_username=args.db_username,
|
||||
db_password=args.db_password,
|
||||
anon_perms=anon_perms,
|
||||
admin_username=args.admin_user,
|
||||
admin_password=args.admin_password,
|
||||
reuseport=args.reuseport,
|
||||
)
|
||||
server = hashserv.create_server((args.address, args.port), db, args.prefix)
|
||||
server.serve_forever()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
ret = main()
|
||||
except Exception:
|
||||
ret = 1
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
@@ -7,15 +7,24 @@
|
||||
# Copyright (C) 2011 Mentor Graphics Corporation
|
||||
# Copyright (C) 2011-2015 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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 logging
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
import signal
|
||||
|
||||
bindir = os.path.dirname(__file__)
|
||||
topdir = os.path.dirname(bindir)
|
||||
@@ -27,13 +36,14 @@ import bb.msg
|
||||
logger = bb.msg.logger_create('bitbake-layers', sys.stdout)
|
||||
|
||||
def main():
|
||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
||||
parser = argparse.ArgumentParser(
|
||||
description="BitBake layers utility",
|
||||
epilog="Use %(prog)s <subcommand> --help to get help on a specific command",
|
||||
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='Forced execution: can be specified multiple times. -F will force add without recipe parse verification and -FF will additionally force the run withput layer parsing.', action='count', default=0)
|
||||
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()
|
||||
@@ -52,31 +62,25 @@ def main():
|
||||
|
||||
# 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,
|
||||
level=logger.getEffectiveLevel())
|
||||
bb.msg.logger_create('bitbake-layers', output=sys.stdout, color=global_args.color)
|
||||
|
||||
plugins = []
|
||||
tinfoil = bb.tinfoil.Tinfoil(tracking=True)
|
||||
tinfoil.logger.setLevel(logger.getEffectiveLevel())
|
||||
if global_args.force > 1:
|
||||
bbpaths = []
|
||||
else:
|
||||
try:
|
||||
tinfoil.prepare(True)
|
||||
bbpaths = tinfoil.config_data.getVar('BBPATH').split(':')
|
||||
|
||||
try:
|
||||
for path in ([topdir] + bbpaths):
|
||||
for path in ([topdir] +
|
||||
tinfoil.config_data.getVar('BBPATH').split(':')):
|
||||
pluginpath = os.path.join(path, 'lib', 'bblayers')
|
||||
bb.utils.load_plugins(logger, plugins, pluginpath)
|
||||
|
||||
registered = False
|
||||
for plugin in plugins:
|
||||
if hasattr(plugin, 'tinfoil_init') and global_args.force <= 1:
|
||||
plugin.tinfoil_init(tinfoil)
|
||||
if hasattr(plugin, 'register_commands'):
|
||||
registered = True
|
||||
plugin.register_commands(subparsers)
|
||||
if hasattr(plugin, 'tinfoil_init'):
|
||||
plugin.tinfoil_init(tinfoil)
|
||||
|
||||
if not registered:
|
||||
logger.error("No commands registered - missing plugins?")
|
||||
|
||||
@@ -1,103 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import os
|
||||
import sys,logging
|
||||
import argparse
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
import optparse
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), "lib"))
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)),'lib'))
|
||||
|
||||
import prserv
|
||||
import prserv.serv
|
||||
|
||||
VERSION = "2.0.0"
|
||||
__version__="1.0.0"
|
||||
|
||||
PRHOST_DEFAULT="0.0.0.0"
|
||||
PRHOST_DEFAULT='0.0.0.0'
|
||||
PRPORT_DEFAULT=8585
|
||||
|
||||
def init_logger(logfile, loglevel):
|
||||
numeric_level = getattr(logging, loglevel.upper(), None)
|
||||
if not isinstance(numeric_level, int):
|
||||
raise ValueError("Invalid log level: %s" % loglevel)
|
||||
FORMAT = "%(asctime)-15s %(message)s"
|
||||
logging.basicConfig(level=numeric_level, filename=logfile, format=FORMAT)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="BitBake PR Server. Version=%s" % VERSION,
|
||||
formatter_class=argparse.RawTextHelpFormatter)
|
||||
parser = optparse.OptionParser(
|
||||
version="Bitbake PR Service Core version %s, %%prog version %s" % (prserv.__version__, __version__),
|
||||
usage = "%prog < --start | --stop > [options]")
|
||||
|
||||
parser.add_argument(
|
||||
"-f",
|
||||
"--file",
|
||||
default="prserv.sqlite3",
|
||||
help="database filename (default: prserv.sqlite3)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--log",
|
||||
default="prserv.log",
|
||||
help="log filename(default: prserv.log)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--loglevel",
|
||||
default="INFO",
|
||||
help="logging level, i.e. CRITICAL, ERROR, WARNING, INFO, DEBUG",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--start",
|
||||
action="store_true",
|
||||
help="start daemon",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--stop",
|
||||
action="store_true",
|
||||
help="stop daemon",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--host",
|
||||
help="ip address to bind",
|
||||
default=PRHOST_DEFAULT,
|
||||
)
|
||||
parser.add_argument(
|
||||
"--port",
|
||||
type=int,
|
||||
default=PRPORT_DEFAULT,
|
||||
help="port number (default: 8585)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--read-only",
|
||||
action="store_true",
|
||||
help="open database in read-only mode",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-u",
|
||||
"--upstream",
|
||||
default=os.environ.get("PRSERVER_UPSTREAM", None),
|
||||
help="Upstream PR service (host:port)",
|
||||
)
|
||||
parser.add_option("-f", "--file", help="database filename(default: prserv.sqlite3)", action="store",
|
||||
dest="dbfile", type="string", default="prserv.sqlite3")
|
||||
parser.add_option("-l", "--log", help="log filename(default: prserv.log)", action="store",
|
||||
dest="logfile", type="string", default="prserv.log")
|
||||
parser.add_option("--loglevel", help="logging level, i.e. CRITICAL, ERROR, WARNING, INFO, DEBUG",
|
||||
action = "store", type="string", dest="loglevel", default = "INFO")
|
||||
parser.add_option("--start", help="start daemon",
|
||||
action="store_true", dest="start")
|
||||
parser.add_option("--stop", help="stop daemon",
|
||||
action="store_true", dest="stop")
|
||||
parser.add_option("--host", help="ip address to bind", action="store",
|
||||
dest="host", type="string", default=PRHOST_DEFAULT)
|
||||
parser.add_option("--port", help="port number(default: 8585)", action="store",
|
||||
dest="port", type="int", default=PRPORT_DEFAULT)
|
||||
|
||||
args = parser.parse_args()
|
||||
init_logger(os.path.abspath(args.log), args.loglevel)
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
prserv.init_logger(os.path.abspath(options.logfile),options.loglevel)
|
||||
|
||||
if args.start:
|
||||
ret=prserv.serv.start_daemon(
|
||||
args.file,
|
||||
args.host,
|
||||
args.port,
|
||||
os.path.abspath(args.log),
|
||||
args.read_only,
|
||||
args.upstream
|
||||
)
|
||||
elif args.stop:
|
||||
ret=prserv.serv.stop_daemon(args.host, args.port)
|
||||
if options.start:
|
||||
ret=prserv.serv.start_daemon(options.dbfile, options.host, options.port,os.path.abspath(options.logfile))
|
||||
elif options.stop:
|
||||
ret=prserv.serv.stop_daemon(options.host, options.port)
|
||||
else:
|
||||
ret=parser.print_help()
|
||||
return ret
|
||||
|
||||
@@ -2,26 +2,32 @@
|
||||
#
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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, logging
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
|
||||
|
||||
import unittest
|
||||
try:
|
||||
import bb
|
||||
import hashserv
|
||||
import prserv
|
||||
import layerindexlib
|
||||
except RuntimeError as exc:
|
||||
sys.exit(str(exc))
|
||||
|
||||
tests = ["bb.tests.codeparser",
|
||||
"bb.tests.color",
|
||||
"bb.tests.cooker",
|
||||
"bb.tests.cow",
|
||||
"bb.tests.data",
|
||||
@@ -29,12 +35,8 @@ tests = ["bb.tests.codeparser",
|
||||
"bb.tests.fetch",
|
||||
"bb.tests.parse",
|
||||
"bb.tests.persist_data",
|
||||
"bb.tests.runqueue",
|
||||
"bb.tests.siggen",
|
||||
"bb.tests.utils",
|
||||
"bb.tests.compression",
|
||||
"hashserv.tests",
|
||||
"prserv.tests",
|
||||
"layerindexlib.tests.layerindexobj",
|
||||
"layerindexlib.tests.restapi",
|
||||
"layerindexlib.tests.cooker"]
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# Copyright (C) 2020 Richard Purdie
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
import logging
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
|
||||
|
||||
import bb
|
||||
|
||||
bb.utils.check_system_locale()
|
||||
|
||||
# Users shouldn't be running this code directly
|
||||
if len(sys.argv) != 11 or not sys.argv[1].startswith("decafbad"):
|
||||
print("bitbake-server is meant for internal execution by bitbake itself, please don't use it standalone.")
|
||||
sys.exit(1)
|
||||
|
||||
import bb.server.process
|
||||
|
||||
lockfd = int(sys.argv[2])
|
||||
readypipeinfd = int(sys.argv[3])
|
||||
logfile = sys.argv[4]
|
||||
lockname = sys.argv[5]
|
||||
sockname = sys.argv[6]
|
||||
timeout = float(sys.argv[7])
|
||||
profile = bool(int(sys.argv[8]))
|
||||
xmlrpcinterface = (sys.argv[9], int(sys.argv[10]))
|
||||
if xmlrpcinterface[0] == "None":
|
||||
xmlrpcinterface = (None, xmlrpcinterface[1])
|
||||
|
||||
# Replace standard fds with our own
|
||||
with open('/dev/null', 'r') as si:
|
||||
os.dup2(si.fileno(), sys.stdin.fileno())
|
||||
|
||||
so = open(logfile, 'a+')
|
||||
os.dup2(so.fileno(), sys.stdout.fileno())
|
||||
os.dup2(so.fileno(), sys.stderr.fileno())
|
||||
|
||||
# Have stdout and stderr be the same so log output matches chronologically
|
||||
# and there aren't two seperate buffers
|
||||
sys.stderr = sys.stdout
|
||||
|
||||
logger = logging.getLogger("BitBake")
|
||||
# Ensure logging messages get sent to the UI as events
|
||||
handler = bb.event.LogHandler()
|
||||
logger.addHandler(handler)
|
||||
|
||||
bb.server.process.execServer(lockfd, readypipeinfd, lockname, sockname, timeout, xmlrpcinterface, profile)
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
|
||||
from bb import fetch2
|
||||
import logging
|
||||
@@ -19,12 +13,11 @@ import signal
|
||||
import pickle
|
||||
import traceback
|
||||
import queue
|
||||
import shlex
|
||||
import subprocess
|
||||
from multiprocessing import Lock
|
||||
from threading import Thread
|
||||
|
||||
bb.utils.check_system_locale()
|
||||
if sys.getfilesystemencoding() != "utf-8":
|
||||
sys.exit("Please use a locale setting which supports UTF-8 (such as LANG=en_US.UTF-8).\nPython can't change the filesystem locale after loading so we need a UTF-8 when Python starts or things won't work.")
|
||||
|
||||
# Users shouldn't be running this code directly
|
||||
if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"):
|
||||
@@ -69,6 +62,7 @@ if 0:
|
||||
format_str = "%(levelname)s: %(message)s"
|
||||
conlogformat = bb.msg.BBLogFormatter(format_str)
|
||||
consolelog = logging.FileHandler(logfilename)
|
||||
bb.msg.addDefaultlogFilter(consolelog)
|
||||
consolelog.setFormatter(conlogformat)
|
||||
logger.addHandler(consolelog)
|
||||
|
||||
@@ -91,19 +85,19 @@ def worker_fire_prepickled(event):
|
||||
worker_thread_exit = False
|
||||
|
||||
def worker_flush(worker_queue):
|
||||
worker_queue_int = bytearray()
|
||||
worker_queue_int = b""
|
||||
global worker_pipe, worker_thread_exit
|
||||
|
||||
while True:
|
||||
try:
|
||||
worker_queue_int.extend(worker_queue.get(True, 1))
|
||||
worker_queue_int = worker_queue_int + worker_queue.get(True, 1)
|
||||
except queue.Empty:
|
||||
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.extend(worker_queue.get())
|
||||
worker_queue_int = worker_queue_int + worker_queue.get()
|
||||
written = os.write(worker_pipe, worker_queue_int)
|
||||
worker_queue_int = worker_queue_int[written:]
|
||||
except (IOError, OSError) as e:
|
||||
@@ -121,10 +115,9 @@ def worker_child_fire(event, d):
|
||||
|
||||
data = b"<event>" + pickle.dumps(event) + b"</event>"
|
||||
try:
|
||||
with bb.utils.lock_timeout(worker_pipe_lock):
|
||||
while(len(data)):
|
||||
written = worker_pipe.write(data)
|
||||
data = data[written:]
|
||||
worker_pipe_lock.acquire()
|
||||
worker_pipe.write(data)
|
||||
worker_pipe_lock.release()
|
||||
except IOError:
|
||||
sigterm_handler(None, None)
|
||||
raise
|
||||
@@ -143,59 +136,40 @@ def sigterm_handler(signum, frame):
|
||||
os.killpg(0, signal.SIGTERM)
|
||||
sys.exit()
|
||||
|
||||
def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
|
||||
|
||||
fn = runtask['fn']
|
||||
task = runtask['task']
|
||||
taskname = runtask['taskname']
|
||||
taskhash = runtask['taskhash']
|
||||
unihash = runtask['unihash']
|
||||
appends = runtask['appends']
|
||||
layername = runtask['layername']
|
||||
taskdepdata = runtask['taskdepdata']
|
||||
quieterrors = runtask['quieterrors']
|
||||
def fork_off_task(cfg, data, databuilder, workerdata, fn, task, taskname, taskhash, unihash, appends, taskdepdata, extraconfigdata, quieterrors=False, dry_run_exec=False):
|
||||
# We need to setup the environment BEFORE the fork, since
|
||||
# a fork() or exec*() activates PSEUDO...
|
||||
|
||||
envbackup = {}
|
||||
fakeroot = False
|
||||
fakeenv = {}
|
||||
umask = None
|
||||
|
||||
uid = os.getuid()
|
||||
gid = os.getgid()
|
||||
|
||||
taskdep = runtask['taskdep']
|
||||
taskdep = workerdata["taskdeps"][fn]
|
||||
if 'umask' in taskdep and taskname in taskdep['umask']:
|
||||
umask = taskdep['umask'][taskname]
|
||||
elif workerdata["umask"]:
|
||||
umask = workerdata["umask"]
|
||||
if umask:
|
||||
# umask might come in as a number or text string..
|
||||
try:
|
||||
umask = int(umask, 8)
|
||||
umask = int(taskdep['umask'][taskname],8)
|
||||
except TypeError:
|
||||
pass
|
||||
umask = taskdep['umask'][taskname]
|
||||
|
||||
dry_run = cfg.dry_run or runtask['dry_run']
|
||||
dry_run = cfg.dry_run or dry_run_exec
|
||||
|
||||
# We can't use the fakeroot environment in a dry run as it possibly hasn't been built
|
||||
if 'fakeroot' in taskdep and taskname in taskdep['fakeroot'] and not dry_run:
|
||||
fakeroot = True
|
||||
envvars = (runtask['fakerootenv'] or "").split()
|
||||
for key, value in (var.split('=',1) for var in envvars):
|
||||
envvars = (workerdata["fakerootenv"][fn] or "").split()
|
||||
for key, value in (var.split('=') for var in envvars):
|
||||
envbackup[key] = os.environ.get(key)
|
||||
os.environ[key] = value
|
||||
fakeenv[key] = value
|
||||
|
||||
fakedirs = (runtask['fakerootdirs'] or "").split()
|
||||
fakedirs = (workerdata["fakerootdirs"][fn] or "").split()
|
||||
for p in fakedirs:
|
||||
bb.utils.mkdirhier(p)
|
||||
logger.debug2('Running %s:%s under fakeroot, fakedirs: %s' %
|
||||
logger.debug(2, 'Running %s:%s under fakeroot, fakedirs: %s' %
|
||||
(fn, taskname, ', '.join(fakedirs)))
|
||||
else:
|
||||
envvars = (runtask['fakerootnoenv'] or "").split()
|
||||
for key, value in (var.split('=',1) for var in envvars):
|
||||
envvars = (workerdata["fakerootnoenv"][fn] or "").split()
|
||||
for key, value in (var.split('=') for var in envvars):
|
||||
envbackup[key] = os.environ.get(key)
|
||||
os.environ[key] = value
|
||||
fakeenv[key] = value
|
||||
@@ -218,6 +192,9 @@ def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
|
||||
global worker_pipe_lock
|
||||
pipein.close()
|
||||
|
||||
signal.signal(signal.SIGTERM, sigterm_handler)
|
||||
# Let SIGHUP exit as SIGTERM
|
||||
signal.signal(signal.SIGHUP, sigterm_handler)
|
||||
bb.utils.signal_on_parent_exit("SIGTERM")
|
||||
|
||||
# Save out the PID so that the event can include it the
|
||||
@@ -232,26 +209,19 @@ def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
|
||||
# This ensures signals sent to the controlling terminal like Ctrl+C
|
||||
# don't stop the child processes.
|
||||
os.setsid()
|
||||
# No stdin
|
||||
newsi = os.open(os.devnull, os.O_RDWR)
|
||||
os.dup2(newsi, sys.stdin.fileno())
|
||||
|
||||
signal.signal(signal.SIGTERM, sigterm_handler)
|
||||
# Let SIGHUP exit as SIGTERM
|
||||
signal.signal(signal.SIGHUP, sigterm_handler)
|
||||
|
||||
# No stdin & stdout
|
||||
# stdout is used as a status report channel and must not be used by child processes.
|
||||
dumbio = os.open(os.devnull, os.O_RDWR)
|
||||
os.dup2(dumbio, sys.stdin.fileno())
|
||||
os.dup2(dumbio, sys.stdout.fileno())
|
||||
|
||||
if umask is not None:
|
||||
if umask:
|
||||
os.umask(umask)
|
||||
|
||||
try:
|
||||
bb_cache = bb.cache.NoCache(databuilder)
|
||||
(realfn, virtual, mc) = bb.cache.virtualfn2realfn(fn)
|
||||
the_data = databuilder.mcdata[mc]
|
||||
the_data.setVar("BB_WORKERCONTEXT", "1")
|
||||
the_data.setVar("BB_TASKDEPDATA", taskdepdata)
|
||||
the_data.setVar('BB_CURRENTTASK', taskname.replace("do_", ""))
|
||||
if cfg.limited_deps:
|
||||
the_data.setVar("BB_LIMITEDDEPS", "1")
|
||||
the_data.setVar("BUILDNAME", workerdata["buildname"])
|
||||
@@ -261,24 +231,14 @@ def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
|
||||
the_data.setVar(varname, value)
|
||||
|
||||
bb.parse.siggen.set_taskdata(workerdata["sigdata"])
|
||||
if "newhashes" in workerdata:
|
||||
bb.parse.siggen.set_taskhashes(workerdata["newhashes"])
|
||||
ret = 0
|
||||
|
||||
the_data = databuilder.parseRecipe(fn, appends, layername)
|
||||
the_data = bb_cache.loadDataFull(fn, appends)
|
||||
the_data.setVar('BB_TASKHASH', taskhash)
|
||||
the_data.setVar('BB_UNIHASH', unihash)
|
||||
bb.parse.siggen.setup_datacache_from_datastore(fn, the_data)
|
||||
|
||||
bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN"), taskname.replace("do_", "")))
|
||||
|
||||
if not bb.utils.to_boolean(the_data.getVarFlag(taskname, 'network')):
|
||||
if bb.utils.is_local_uid(uid):
|
||||
logger.debug("Attempting to disable network for %s" % taskname)
|
||||
bb.utils.disable_network(uid, gid)
|
||||
else:
|
||||
logger.debug("Skipping disable network for %s since %s is not a local uid." % (taskname, uid))
|
||||
|
||||
# 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
|
||||
exports = bb.data.exported_vars(the_data)
|
||||
@@ -307,20 +267,10 @@ def fork_off_task(cfg, data, databuilder, workerdata, extraconfigdata, runtask):
|
||||
if not quieterrors:
|
||||
logger.critical(traceback.format_exc())
|
||||
os._exit(1)
|
||||
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
try:
|
||||
if dry_run:
|
||||
return 0
|
||||
try:
|
||||
ret = bb.build.exec_task(fn, taskname, the_data, cfg.profile)
|
||||
finally:
|
||||
if fakeroot:
|
||||
fakerootcmd = shlex.split(the_data.getVar("FAKEROOTCMD"))
|
||||
subprocess.run(fakerootcmd + ['-S'], check=True, stdout=subprocess.PIPE)
|
||||
return ret
|
||||
return bb.build.exec_task(fn, taskname, the_data, cfg.profile)
|
||||
except:
|
||||
os._exit(1)
|
||||
if not profiling:
|
||||
@@ -352,12 +302,12 @@ class runQueueWorkerPipe():
|
||||
if pipeout:
|
||||
pipeout.close()
|
||||
bb.utils.nonblockingfd(self.input)
|
||||
self.queue = bytearray()
|
||||
self.queue = b""
|
||||
|
||||
def read(self):
|
||||
start = len(self.queue)
|
||||
try:
|
||||
self.queue.extend(self.input.read(102400) or b"")
|
||||
self.queue = self.queue + (self.input.read(102400) or b"")
|
||||
except (OSError, IOError) as e:
|
||||
if e.errno != errno.EAGAIN:
|
||||
raise
|
||||
@@ -365,9 +315,7 @@ class runQueueWorkerPipe():
|
||||
end = len(self.queue)
|
||||
index = self.queue.find(b"</event>")
|
||||
while index != -1:
|
||||
msg = self.queue[:index+8]
|
||||
assert msg.startswith(b"<event>") and msg.count(b"<event>") == 1
|
||||
worker_fire_prepickled(msg)
|
||||
worker_fire_prepickled(self.queue[:index+8])
|
||||
self.queue = self.queue[index+8:]
|
||||
index = self.queue.find(b"</event>")
|
||||
return (end > start)
|
||||
@@ -385,7 +333,7 @@ class BitbakeWorker(object):
|
||||
def __init__(self, din):
|
||||
self.input = din
|
||||
bb.utils.nonblockingfd(self.input)
|
||||
self.queue = bytearray()
|
||||
self.queue = b""
|
||||
self.cookercfg = None
|
||||
self.databuilder = None
|
||||
self.data = None
|
||||
@@ -419,14 +367,13 @@ class BitbakeWorker(object):
|
||||
if len(r) == 0:
|
||||
# EOF on pipe, server must have terminated
|
||||
self.sigterm_exception(signal.SIGTERM, None)
|
||||
self.queue.extend(r)
|
||||
self.queue = self.queue + r
|
||||
except (OSError, IOError):
|
||||
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"newtaskhashes", self.handle_newtaskhashes)
|
||||
self.handle_item(b"runtask", self.handle_runtask)
|
||||
self.handle_item(b"finishnow", self.handle_finishnow)
|
||||
self.handle_item(b"ping", self.handle_ping)
|
||||
@@ -439,35 +386,19 @@ class BitbakeWorker(object):
|
||||
while self.process_waitpid():
|
||||
continue
|
||||
|
||||
|
||||
def handle_item(self, item, func):
|
||||
opening_tag = b"<" + item + b">"
|
||||
if not self.queue.startswith(opening_tag):
|
||||
return
|
||||
|
||||
tag_len = len(opening_tag)
|
||||
if len(self.queue) < tag_len + 4:
|
||||
# we need to receive more data
|
||||
return
|
||||
header = self.queue[tag_len:tag_len + 4]
|
||||
payload_len = int.from_bytes(header, 'big')
|
||||
# closing tag has length (tag_len + 1)
|
||||
if len(self.queue) < tag_len * 2 + 1 + payload_len:
|
||||
# we need to receive more data
|
||||
return
|
||||
|
||||
index = self.queue.find(b"</" + item + b">")
|
||||
if index != -1:
|
||||
try:
|
||||
func(self.queue[(tag_len + 4):index])
|
||||
except pickle.UnpicklingError:
|
||||
workerlog_write("Unable to unpickle data: %s\n" % ":".join("{:02x}".format(c) for c in self.queue))
|
||||
raise
|
||||
self.queue = self.queue[(index + len(b"</") + len(item) + len(b">")):]
|
||||
if self.queue.startswith(b"<" + item + b">"):
|
||||
index = self.queue.find(b"</" + item + b">")
|
||||
while index != -1:
|
||||
func(self.queue[(len(item) + 2):index])
|
||||
self.queue = self.queue[(index + len(item) + 3):]
|
||||
index = self.queue.find(b"</" + item + b">")
|
||||
|
||||
def handle_cookercfg(self, data):
|
||||
self.cookercfg = pickle.loads(data)
|
||||
self.databuilder = bb.cookerdata.CookerDataBuilder(self.cookercfg, worker=True)
|
||||
self.databuilder.parseBaseConfiguration(worker=True)
|
||||
self.databuilder.parseBaseConfiguration()
|
||||
self.data = self.databuilder.data
|
||||
|
||||
def handle_extraconfigdata(self, data):
|
||||
@@ -475,17 +406,12 @@ class BitbakeWorker(object):
|
||||
|
||||
def handle_workerdata(self, data):
|
||||
self.workerdata = pickle.loads(data)
|
||||
bb.build.verboseShellLogging = self.workerdata["build_verbose_shell"]
|
||||
bb.build.verboseStdoutLogging = self.workerdata["build_verbose_stdout"]
|
||||
bb.msg.loggerDefaultLogLevel = self.workerdata["logdefaultlevel"]
|
||||
bb.msg.loggerDefaultDebugLevel = self.workerdata["logdefaultdebug"]
|
||||
bb.msg.loggerDefaultVerbose = self.workerdata["logdefaultverbose"]
|
||||
bb.msg.loggerVerboseLogs = self.workerdata["logdefaultverboselogs"]
|
||||
bb.msg.loggerDefaultDomains = self.workerdata["logdefaultdomain"]
|
||||
for mc in self.databuilder.mcdata:
|
||||
self.databuilder.mcdata[mc].setVar("PRSERV_HOST", self.workerdata["prhost"])
|
||||
self.databuilder.mcdata[mc].setVar("BB_HASHSERVE", self.workerdata["hashservaddr"])
|
||||
self.databuilder.mcdata[mc].setVar("__bbclasstype", "recipe")
|
||||
|
||||
def handle_newtaskhashes(self, data):
|
||||
self.workerdata["newhashes"] = pickle.loads(data)
|
||||
|
||||
def handle_ping(self, _):
|
||||
workerlog_write("Handling ping\n")
|
||||
@@ -500,15 +426,11 @@ class BitbakeWorker(object):
|
||||
sys.exit(0)
|
||||
|
||||
def handle_runtask(self, data):
|
||||
runtask = pickle.loads(data)
|
||||
|
||||
fn = runtask['fn']
|
||||
task = runtask['task']
|
||||
taskname = runtask['taskname']
|
||||
|
||||
fn, task, taskname, taskhash, unihash, quieterrors, appends, taskdepdata, dry_run_exec = 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, self.extraconfigdata, runtask)
|
||||
pid, pipein, pipeout = fork_off_task(self.cookercfg, self.data, self.databuilder, self.workerdata, fn, task, taskname, taskhash, unihash, appends, taskdepdata, self.extraconfigdata, quieterrors, dry_run_exec)
|
||||
|
||||
self.build_pids[pid] = task
|
||||
self.build_pipes[pid] = runQueueWorkerPipe(pipein, pipeout)
|
||||
|
||||
@@ -572,11 +494,9 @@ except BaseException as e:
|
||||
import traceback
|
||||
sys.stderr.write(traceback.format_exc())
|
||||
sys.stderr.write(str(e))
|
||||
finally:
|
||||
worker_thread_exit = True
|
||||
worker_thread.join()
|
||||
|
||||
workerlog_write("exiting")
|
||||
if not normalexit:
|
||||
sys.exit(1)
|
||||
worker_thread_exit = True
|
||||
worker_thread.join()
|
||||
|
||||
workerlog_write("exitting")
|
||||
sys.exit(0)
|
||||
|
||||
531
bitbake/bin/bitdoc
Executable file
531
bitbake/bin/bitdoc
Executable file
@@ -0,0 +1,531 @@
|
||||
#!/usr/bin/env python3
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (C) 2005 Holger Hans Peter Freyther
|
||||
#
|
||||
# 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 optparse, os, sys
|
||||
|
||||
# bitbake
|
||||
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__), 'lib'))
|
||||
import bb
|
||||
import bb.parse
|
||||
from string import split, join
|
||||
|
||||
__version__ = "0.0.2"
|
||||
|
||||
class HTMLFormatter:
|
||||
"""
|
||||
Simple class to help to generate some sort of HTML files. It is
|
||||
quite inferior solution compared to docbook, gtkdoc, doxygen but it
|
||||
should work for now.
|
||||
We've a global introduction site (index.html) and then one site for
|
||||
the list of keys (alphabetical sorted) and one for the list of groups,
|
||||
one site for each key with links to the relations and groups.
|
||||
|
||||
index.html
|
||||
all_keys.html
|
||||
all_groups.html
|
||||
groupNAME.html
|
||||
keyNAME.html
|
||||
"""
|
||||
|
||||
def replace(self, text, *pairs):
|
||||
"""
|
||||
From pydoc... almost identical at least
|
||||
"""
|
||||
while pairs:
|
||||
(a, b) = pairs[0]
|
||||
text = join(split(text, a), b)
|
||||
pairs = pairs[1:]
|
||||
return text
|
||||
def escape(self, text):
|
||||
"""
|
||||
Escape string to be conform HTML
|
||||
"""
|
||||
return self.replace(text,
|
||||
('&', '&'),
|
||||
('<', '<' ),
|
||||
('>', '>' ) )
|
||||
def createNavigator(self):
|
||||
"""
|
||||
Create the navgiator
|
||||
"""
|
||||
return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
|
||||
<tr valign="middle">
|
||||
<td><a accesskey="g" href="index.html">Home</a></td>
|
||||
<td><a accesskey="n" href="all_groups.html">Groups</a></td>
|
||||
<td><a accesskey="u" href="all_keys.html">Keys</a></td>
|
||||
</tr></table>
|
||||
"""
|
||||
|
||||
def relatedKeys(self, item):
|
||||
"""
|
||||
Create HTML to link to foreign keys
|
||||
"""
|
||||
|
||||
if len(item.related()) == 0:
|
||||
return ""
|
||||
|
||||
txt = "<p><b>See also:</b><br>"
|
||||
txts = []
|
||||
for it in item.related():
|
||||
txts.append("""<a href="key%(it)s.html">%(it)s</a>""" % vars() )
|
||||
|
||||
return txt + ",".join(txts)
|
||||
|
||||
def groups(self, item):
|
||||
"""
|
||||
Create HTML to link to related groups
|
||||
"""
|
||||
|
||||
if len(item.groups()) == 0:
|
||||
return ""
|
||||
|
||||
|
||||
txt = "<p><b>See also:</b><br>"
|
||||
txts = []
|
||||
for group in item.groups():
|
||||
txts.append( """<a href="group%s.html">%s</a> """ % (group, group) )
|
||||
|
||||
return txt + ",".join(txts)
|
||||
|
||||
|
||||
def createKeySite(self, item):
|
||||
"""
|
||||
Create a site for a key. It contains the header/navigator, a heading,
|
||||
the description, links to related keys and to the groups.
|
||||
"""
|
||||
|
||||
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Key %s</title></head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
%s
|
||||
<h2><span class="refentrytitle">%s</span></h2>
|
||||
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Synopsis</h2>
|
||||
<p>
|
||||
%s
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Related Keys</h2>
|
||||
<p>
|
||||
%s
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Groups</h2>
|
||||
<p>
|
||||
%s
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
""" % (item.name(), self.createNavigator(), item.name(),
|
||||
self.escape(item.description()), self.relatedKeys(item), self.groups(item))
|
||||
|
||||
def createGroupsSite(self, doc):
|
||||
"""
|
||||
Create the Group Overview site
|
||||
"""
|
||||
|
||||
groups = ""
|
||||
sorted_groups = sorted(doc.groups())
|
||||
for group in sorted_groups:
|
||||
groups += """<a href="group%s.html">%s</a><br>""" % (group, group)
|
||||
|
||||
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Group overview</title></head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
%s
|
||||
<h2>Available Groups</h2>
|
||||
%s
|
||||
</body>
|
||||
""" % (self.createNavigator(), groups)
|
||||
|
||||
def createIndex(self):
|
||||
"""
|
||||
Create the index file
|
||||
"""
|
||||
|
||||
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Bitbake Documentation</title></head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
%s
|
||||
<h2>Documentation Entrance</h2>
|
||||
<a href="all_groups.html">All available groups</a><br>
|
||||
<a href="all_keys.html">All available keys</a><br>
|
||||
</body>
|
||||
""" % self.createNavigator()
|
||||
|
||||
def createKeysSite(self, doc):
|
||||
"""
|
||||
Create Overview of all avilable keys
|
||||
"""
|
||||
keys = ""
|
||||
sorted_keys = sorted(doc.doc_keys())
|
||||
for key in sorted_keys:
|
||||
keys += """<a href="key%s.html">%s</a><br>""" % (key, key)
|
||||
|
||||
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Key overview</title></head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
%s
|
||||
<h2>Available Keys</h2>
|
||||
%s
|
||||
</body>
|
||||
""" % (self.createNavigator(), keys)
|
||||
|
||||
def createGroupSite(self, gr, items, _description = None):
|
||||
"""
|
||||
Create a site for a group:
|
||||
Group the name of the group, items contain the name of the keys
|
||||
inside this group
|
||||
"""
|
||||
groups = ""
|
||||
description = ""
|
||||
|
||||
# create a section with the group descriptions
|
||||
if _description:
|
||||
description += "<h2 Description of Grozp %s</h2>" % gr
|
||||
description += _description
|
||||
|
||||
items.sort(lambda x, y:cmp(x.name(), y.name()))
|
||||
for group in items:
|
||||
groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
|
||||
|
||||
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Group %s</title></head>
|
||||
<link rel="stylesheet" href="style.css" type="text/css">
|
||||
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
|
||||
%s
|
||||
%s
|
||||
<div class="refsynopsisdiv">
|
||||
<h2>Keys in Group %s</h2>
|
||||
<pre class="synopsis">
|
||||
%s
|
||||
</pre>
|
||||
</div>
|
||||
</body>
|
||||
""" % (gr, self.createNavigator(), description, gr, groups)
|
||||
|
||||
|
||||
|
||||
def createCSS(self):
|
||||
"""
|
||||
Create the CSS file
|
||||
"""
|
||||
return """.synopsis, .classsynopsis
|
||||
{
|
||||
background: #eeeeee;
|
||||
border: solid 1px #aaaaaa;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.programlisting
|
||||
{
|
||||
background: #eeeeff;
|
||||
border: solid 1px #aaaaff;
|
||||
padding: 0.5em;
|
||||
}
|
||||
.variablelist
|
||||
{
|
||||
padding: 4px;
|
||||
margin-left: 3em;
|
||||
}
|
||||
.variablelist td:first-child
|
||||
{
|
||||
vertical-align: top;
|
||||
}
|
||||
table.navigation
|
||||
{
|
||||
background: #ffeeee;
|
||||
border: solid 1px #ffaaaa;
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.navigation a
|
||||
{
|
||||
color: #770000;
|
||||
}
|
||||
.navigation a:visited
|
||||
{
|
||||
color: #550000;
|
||||
}
|
||||
.navigation .title
|
||||
{
|
||||
font-size: 200%;
|
||||
}
|
||||
div.refnamediv
|
||||
{
|
||||
margin-top: 2em;
|
||||
}
|
||||
div.gallery-float
|
||||
{
|
||||
float: left;
|
||||
padding: 10px;
|
||||
}
|
||||
div.gallery-float img
|
||||
{
|
||||
border-style: none;
|
||||
}
|
||||
div.gallery-spacer
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
a
|
||||
{
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
color: #FF0000;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class DocumentationItem:
|
||||
"""
|
||||
A class to hold information about a configuration
|
||||
item. It contains the key name, description, a list of related names,
|
||||
and the group this item is contained in.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._groups = []
|
||||
self._related = []
|
||||
self._name = ""
|
||||
self._desc = ""
|
||||
|
||||
def groups(self):
|
||||
return self._groups
|
||||
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
def description(self):
|
||||
return self._desc
|
||||
|
||||
def related(self):
|
||||
return self._related
|
||||
|
||||
def setName(self, name):
|
||||
self._name = name
|
||||
|
||||
def setDescription(self, desc):
|
||||
self._desc = desc
|
||||
|
||||
def addGroup(self, group):
|
||||
self._groups.append(group)
|
||||
|
||||
def addRelation(self, relation):
|
||||
self._related.append(relation)
|
||||
|
||||
def sort(self):
|
||||
self._related.sort()
|
||||
self._groups.sort()
|
||||
|
||||
|
||||
class Documentation:
|
||||
"""
|
||||
Holds the documentation... with mappings from key to items...
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.__keys = {}
|
||||
self.__groups = {}
|
||||
|
||||
def insert_doc_item(self, item):
|
||||
"""
|
||||
Insert the Doc Item into the internal list
|
||||
of representation
|
||||
"""
|
||||
item.sort()
|
||||
self.__keys[item.name()] = item
|
||||
|
||||
for group in item.groups():
|
||||
if not group in self.__groups:
|
||||
self.__groups[group] = []
|
||||
self.__groups[group].append(item)
|
||||
self.__groups[group].sort()
|
||||
|
||||
|
||||
def doc_item(self, key):
|
||||
"""
|
||||
Return the DocumentationInstance describing the key
|
||||
"""
|
||||
try:
|
||||
return self.__keys[key]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def doc_keys(self):
|
||||
"""
|
||||
Return the documented KEYS (names)
|
||||
"""
|
||||
return self.__keys.keys()
|
||||
|
||||
def groups(self):
|
||||
"""
|
||||
Return the names of available groups
|
||||
"""
|
||||
return self.__groups.keys()
|
||||
|
||||
def group_content(self, group_name):
|
||||
"""
|
||||
Return a list of keys/names that are in a specefic
|
||||
group or the empty list
|
||||
"""
|
||||
try:
|
||||
return self.__groups[group_name]
|
||||
except KeyError:
|
||||
return []
|
||||
|
||||
|
||||
def parse_cmdline(args):
|
||||
"""
|
||||
Parse the CMD line and return the result as a n-tuple
|
||||
"""
|
||||
|
||||
parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__, __version__))
|
||||
usage = """%prog [options]
|
||||
|
||||
Create a set of html pages (documentation) for a bitbake.conf....
|
||||
"""
|
||||
|
||||
# Add the needed options
|
||||
parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
|
||||
action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
|
||||
|
||||
parser.add_option( "-o", "--output", help = "Output directory for html files",
|
||||
action = "store", dest = "output", default = "html/" )
|
||||
|
||||
parser.add_option( "-D", "--debug", help = "Increase the debug level",
|
||||
action = "count", dest = "debug", default = 0 )
|
||||
|
||||
parser.add_option( "-v", "--verbose", help = "output more chit-char to the terminal",
|
||||
action = "store_true", dest = "verbose", default = False )
|
||||
|
||||
options, args = parser.parse_args( sys.argv )
|
||||
|
||||
bb.msg.init_msgconfig(options.verbose, options.debug)
|
||||
|
||||
return options.config, options.output
|
||||
|
||||
def main():
|
||||
"""
|
||||
The main Method
|
||||
"""
|
||||
|
||||
(config_file, output_dir) = parse_cmdline( sys.argv )
|
||||
|
||||
# right to let us load the file now
|
||||
try:
|
||||
documentation = bb.parse.handle( config_file, bb.data.init() )
|
||||
except IOError:
|
||||
bb.fatal( "Unable to open %s" % config_file )
|
||||
except bb.parse.ParseError:
|
||||
bb.fatal( "Unable to parse %s" % config_file )
|
||||
|
||||
if isinstance(documentation, dict):
|
||||
documentation = documentation[""]
|
||||
|
||||
# Assuming we've the file loaded now, we will initialize the 'tree'
|
||||
doc = Documentation()
|
||||
|
||||
# defined states
|
||||
state_begin = 0
|
||||
state_see = 1
|
||||
state_group = 2
|
||||
|
||||
for key in bb.data.keys(documentation):
|
||||
data = documentation.getVarFlag(key, "doc", False)
|
||||
if not data:
|
||||
continue
|
||||
|
||||
# The Documentation now starts
|
||||
doc_ins = DocumentationItem()
|
||||
doc_ins.setName(key)
|
||||
|
||||
|
||||
tokens = data.split(' ')
|
||||
state = state_begin
|
||||
string= ""
|
||||
for token in tokens:
|
||||
token = token.strip(',')
|
||||
|
||||
if not state == state_see and token == "@see":
|
||||
state = state_see
|
||||
continue
|
||||
elif not state == state_group and token == "@group":
|
||||
state = state_group
|
||||
continue
|
||||
|
||||
if state == state_begin:
|
||||
string += " %s" % token
|
||||
elif state == state_see:
|
||||
doc_ins.addRelation(token)
|
||||
elif state == state_group:
|
||||
doc_ins.addGroup(token)
|
||||
|
||||
# set the description
|
||||
doc_ins.setDescription(string)
|
||||
doc.insert_doc_item(doc_ins)
|
||||
|
||||
# let us create the HTML now
|
||||
bb.utils.mkdirhier(output_dir)
|
||||
os.chdir(output_dir)
|
||||
|
||||
# Let us create the sites now. We do it in the following order
|
||||
# Start with the index.html. It will point to sites explaining all
|
||||
# keys and groups
|
||||
html_slave = HTMLFormatter()
|
||||
|
||||
f = file('style.css', 'w')
|
||||
print >> f, html_slave.createCSS()
|
||||
|
||||
f = file('index.html', 'w')
|
||||
print >> f, html_slave.createIndex()
|
||||
|
||||
f = file('all_groups.html', 'w')
|
||||
print >> f, html_slave.createGroupsSite(doc)
|
||||
|
||||
f = file('all_keys.html', 'w')
|
||||
print >> f, html_slave.createKeysSite(doc)
|
||||
|
||||
# now for each group create the site
|
||||
for group in doc.groups():
|
||||
f = file('group%s.html' % group, 'w')
|
||||
print >> f, html_slave.createGroupSite(group, doc.group_content(group))
|
||||
|
||||
# now for the keys
|
||||
for key in doc.doc_keys():
|
||||
f = file('key%s.html' % doc.doc_item(key).name(), 'w')
|
||||
print >> f, html_slave.createKeySite(doc.doc_item(key))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,10 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
"""git-make-shallow: make the current git repository shallow
|
||||
|
||||
Remove the history of the specified revisions, then optionally filter the
|
||||
@@ -18,23 +12,19 @@ import itertools
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
|
||||
version = 1.0
|
||||
|
||||
|
||||
git_cmd = ['git', '-c', 'safe.bareRepository=all']
|
||||
|
||||
def main():
|
||||
if sys.version_info < (3, 4, 0):
|
||||
sys.exit('Python 3.4 or greater is required')
|
||||
|
||||
git_dir = check_output(git_cmd + ['rev-parse', '--git-dir']).rstrip()
|
||||
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_cmd + ['fetch', '--unshallow'])
|
||||
check_output(['git', 'fetch', '--unshallow'])
|
||||
except subprocess.CalledProcessError:
|
||||
try:
|
||||
os.unlink(shallow_file)
|
||||
@@ -43,21 +33,21 @@ def main():
|
||||
raise
|
||||
|
||||
args = process_args()
|
||||
revs = check_output(git_cmd + ['rev-list'] + args.revisions).splitlines()
|
||||
revs = check_output(['git', 'rev-list'] + args.revisions).splitlines()
|
||||
|
||||
make_shallow(shallow_file, args.revisions, args.refs)
|
||||
|
||||
ref_revs = check_output(git_cmd + ['rev-list'] + args.refs).splitlines()
|
||||
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_cmd + ['rev-parse', '{}^@'.format(rev)]):
|
||||
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_cmd + ['fsck', '--unreachable'])
|
||||
subprocess.check_call(['git', 'fsck', '--unreachable'])
|
||||
|
||||
|
||||
def process_args():
|
||||
@@ -74,12 +64,12 @@ def process_args():
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.refs:
|
||||
args.refs = check_output(git_cmd + ['rev-parse', '--symbolic-full-name'] + args.refs).splitlines()
|
||||
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_cmd + ['rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines()
|
||||
args.revisions = check_output(['git', 'rev-parse'] + ['%s^{}' % i for i in args.revisions]).splitlines()
|
||||
return args
|
||||
|
||||
|
||||
@@ -97,7 +87,7 @@ def make_shallow(shallow_file, revisions, refs):
|
||||
|
||||
def get_all_refs(ref_filter=None):
|
||||
"""Return all the existing refs in this repository, optionally filtering the refs."""
|
||||
ref_output = check_output(git_cmd + ['for-each-ref', '--format=%(refname)\t%(objecttype)\t%(*objecttype)'])
|
||||
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))
|
||||
@@ -115,7 +105,7 @@ def filter_refs(refs):
|
||||
all_refs = get_all_refs()
|
||||
to_remove = set(all_refs) - set(refs)
|
||||
if to_remove:
|
||||
check_output(['xargs', '-0', '-n', '1'] + git_cmd + ['update-ref', '-d', '--no-deref'],
|
||||
check_output(['xargs', '-0', '-n', '1', 'git', 'update-ref', '-d', '--no-deref'],
|
||||
input=''.join(l + '\0' for l in to_remove))
|
||||
|
||||
|
||||
@@ -128,7 +118,7 @@ def follow_history_intersections(revisions, refs):
|
||||
if rev in seen:
|
||||
continue
|
||||
|
||||
parents = check_output(git_cmd + ['rev-parse', '%s^@' % rev]).splitlines()
|
||||
parents = check_output(['git', 'rev-parse', '%s^@' % rev]).splitlines()
|
||||
|
||||
yield rev
|
||||
seen.add(rev)
|
||||
@@ -136,12 +126,12 @@ def follow_history_intersections(revisions, refs):
|
||||
if not parents:
|
||||
continue
|
||||
|
||||
check_refs = check_output(git_cmd + ['merge-base', '--independent'] + sorted(refs)).splitlines()
|
||||
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_cmd + ['merge-base', parent, ref]).rstrip()
|
||||
merge_base = check_output(['git', 'merge-base', parent, ref]).rstrip()
|
||||
except subprocess.CalledProcessError:
|
||||
continue
|
||||
else:
|
||||
@@ -161,14 +151,14 @@ def iter_except(func, exception, start=None):
|
||||
|
||||
def shrink_repo(git_dir):
|
||||
"""Shrink the newly shallow repository, removing the unreachable objects."""
|
||||
subprocess.check_call(git_cmd + ['reflog', 'expire', '--expire-unreachable=now', '--all'])
|
||||
subprocess.check_call(git_cmd + ['repack', '-ad'])
|
||||
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_cmd + ['prune', '--expire', 'now'])
|
||||
subprocess.check_call(['git', 'prune', '--expire', 'now'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -3,18 +3,27 @@
|
||||
# toaster - shell script to start Toaster
|
||||
|
||||
# Copyright (C) 2013-2015 Intel Corp.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# 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, see http://www.gnu.org/licenses/.
|
||||
|
||||
HELP="
|
||||
Usage 1: source toaster start|stop [webport=<address:port>] [noweb] [nobuild] [toasterdir]
|
||||
Usage: source toaster start|stop [webport=<address:port>] [noweb] [nobuild] [toasterdir]
|
||||
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
|
||||
[webport] Set the development server (default: localhost:8000)
|
||||
[toasterdir] Set absolute path to be used as TOASTER_DIR (default: BUILDDIR/../)
|
||||
Usage 2: source toaster manage [createsuperuser|lsupdates|migrate|makemigrations|checksettings|collectstatic|...]
|
||||
"
|
||||
|
||||
custom_extention()
|
||||
@@ -33,7 +42,7 @@ databaseCheck()
|
||||
$MANAGE migrate --noinput || retval=1
|
||||
|
||||
if [ $retval -eq 1 ]; then
|
||||
echo "Failed migrations, halting system start" 1>&2
|
||||
echo "Failed migrations, aborting system start" 1>&2
|
||||
return $retval
|
||||
fi
|
||||
# Make sure that checksettings can pick up any value for TEMPLATECONF
|
||||
@@ -41,7 +50,7 @@ databaseCheck()
|
||||
$MANAGE checksettings --traceback || retval=1
|
||||
|
||||
if [ $retval -eq 1 ]; then
|
||||
printf "\nError while checking settings; exiting\n"
|
||||
printf "\nError while checking settings; aborting\n"
|
||||
return $retval
|
||||
fi
|
||||
|
||||
@@ -84,7 +93,7 @@ webserverStartAll()
|
||||
echo "Starting webserver..."
|
||||
|
||||
$MANAGE runserver --noreload "$ADDR_PORT" \
|
||||
</dev/null >>${TOASTER_LOGS_DIR}/web.log 2>&1 \
|
||||
</dev/null >>${BUILDDIR}/toaster_web.log 2>&1 \
|
||||
& echo $! >${BUILDDIR}/.toastermain.pid
|
||||
|
||||
sleep 1
|
||||
@@ -181,14 +190,6 @@ WEBSERVER=1
|
||||
export TOASTER_BUILDSERVER=1
|
||||
ADDR_PORT="localhost:8000"
|
||||
TOASTERDIR=`dirname $BUILDDIR`
|
||||
# ${BUILDDIR}/toaster_logs/ became the default location for toaster logs
|
||||
# This is needed for implemented django-log-viewer: https://pypi.org/project/django-log-viewer/
|
||||
# If the directory does not exist, create it.
|
||||
TOASTER_LOGS_DIR="${BUILDDIR}/toaster_logs/"
|
||||
if [ ! -d $TOASTER_LOGS_DIR ]
|
||||
then
|
||||
mkdir $TOASTER_LOGS_DIR
|
||||
fi
|
||||
unset CMD
|
||||
for param in $*; do
|
||||
case $param in
|
||||
@@ -217,21 +218,13 @@ for param in $*; do
|
||||
toasterdir=*)
|
||||
TOASTERDIR="${param#*=}"
|
||||
;;
|
||||
manage )
|
||||
CMD=$param
|
||||
manage_cmd=""
|
||||
;;
|
||||
--help)
|
||||
echo "$HELP"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
if [ "manage" == "$CMD" ] ; then
|
||||
manage_cmd="$manage_cmd $param"
|
||||
else
|
||||
echo "$HELP"
|
||||
exit 1
|
||||
fi
|
||||
echo "$HELP"
|
||||
return 1
|
||||
;;
|
||||
|
||||
esac
|
||||
@@ -256,7 +249,7 @@ fi
|
||||
# 3) the sqlite db if that is being used.
|
||||
# 4) pid's we need to clean up on exit/shutdown
|
||||
export TOASTER_DIR=$TOASTERDIR
|
||||
export BB_ENV_PASSTHROUGH_ADDITIONS="$BB_ENV_PASSTHROUGH_ADDITIONS TOASTER_DIR"
|
||||
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
|
||||
@@ -307,7 +300,7 @@ case $CMD in
|
||||
export BITBAKE_UI='toasterui'
|
||||
if [ $TOASTER_BUILDSERVER -eq 1 ] ; then
|
||||
$MANAGE runbuilds \
|
||||
</dev/null >>${TOASTER_LOGS_DIR}/toaster_runbuilds.log 2>&1 \
|
||||
</dev/null >>${BUILDDIR}/toaster_runbuilds.log 2>&1 \
|
||||
& echo $! >${BUILDDIR}/.runbuilds.pid
|
||||
else
|
||||
echo "Toaster build server not started."
|
||||
@@ -323,10 +316,6 @@ case $CMD in
|
||||
stop_system
|
||||
echo "Successful ${CMD}."
|
||||
;;
|
||||
manage )
|
||||
cd $BBBASEDIR/lib/toaster
|
||||
$MANAGE $manage_cmd
|
||||
;;
|
||||
esac
|
||||
custom_extention toaster_postpend $CMD $ADDR_PORT
|
||||
|
||||
|
||||
@@ -1,12 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (C) 2014 Alex Damian
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# This file re-uses code spread throughout other Bitbake source files.
|
||||
# As such, all other copyrights belong to their own right holders.
|
||||
#
|
||||
#
|
||||
# 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 command takes a filename as a single parameter. The filename is read
|
||||
@@ -19,8 +32,6 @@ import sys
|
||||
import json
|
||||
import pickle
|
||||
import codecs
|
||||
import warnings
|
||||
warnings.simplefilter("default")
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
@@ -30,23 +41,79 @@ sys.path.insert(0, join(dirname(dirname(abspath(__file__))), 'lib'))
|
||||
|
||||
import bb.cooker
|
||||
from bb.ui import toasterui
|
||||
from bb.ui import eventreplay
|
||||
|
||||
class EventPlayer:
|
||||
"""Emulate a connection to a bitbake server."""
|
||||
|
||||
def __init__(self, eventfile, variables):
|
||||
self.eventfile = eventfile
|
||||
self.variables = variables
|
||||
self.eventmask = []
|
||||
|
||||
def waitEvent(self, _timeout):
|
||||
"""Read event from the file."""
|
||||
line = self.eventfile.readline().strip()
|
||||
if not line:
|
||||
return
|
||||
try:
|
||||
event_str = json.loads(line)['vars'].encode('utf-8')
|
||||
event = pickle.loads(codecs.decode(event_str, 'base64'))
|
||||
event_name = "%s.%s" % (event.__module__, event.__class__.__name__)
|
||||
if event_name not in self.eventmask:
|
||||
return
|
||||
return event
|
||||
except ValueError as err:
|
||||
print("Failed loading ", line)
|
||||
raise err
|
||||
|
||||
def runCommand(self, command_line):
|
||||
"""Emulate running a command on the server."""
|
||||
name = command_line[0]
|
||||
|
||||
if name == "getVariable":
|
||||
var_name = command_line[1]
|
||||
variable = self.variables.get(var_name)
|
||||
if variable:
|
||||
return variable['v'], None
|
||||
return None, "Missing variable %s" % var_name
|
||||
|
||||
elif name == "getAllKeysWithFlags":
|
||||
dump = {}
|
||||
flaglist = command_line[1]
|
||||
for key, val in self.variables.items():
|
||||
try:
|
||||
if not key.startswith("__"):
|
||||
dump[key] = {
|
||||
'v': val['v'],
|
||||
'history' : val['history'],
|
||||
}
|
||||
for flag in flaglist:
|
||||
dump[key][flag] = val[flag]
|
||||
except Exception as err:
|
||||
print(err)
|
||||
return (dump, None)
|
||||
|
||||
elif name == 'setEventMask':
|
||||
self.eventmask = command_line[-1]
|
||||
return True, None
|
||||
|
||||
else:
|
||||
raise Exception("Command %s not implemented" % command_line[0])
|
||||
|
||||
def getEventHandle(self):
|
||||
"""
|
||||
This method is called by toasterui.
|
||||
The return value is passed to self.runCommand but not used there.
|
||||
"""
|
||||
pass
|
||||
|
||||
def main(argv):
|
||||
with open(argv[-1]) as eventfile:
|
||||
# load variables from the first line
|
||||
variables = None
|
||||
while line := eventfile.readline().strip():
|
||||
try:
|
||||
variables = json.loads(line)['allvariables']
|
||||
break
|
||||
except (KeyError, json.JSONDecodeError):
|
||||
continue
|
||||
if not variables:
|
||||
sys.exit("Cannot find allvariables entry in event log file %s" % argv[-1])
|
||||
eventfile.seek(0)
|
||||
variables = json.loads(eventfile.readline().strip())['allvariables']
|
||||
|
||||
params = namedtuple('ConfigParams', ['observe_only'])(True)
|
||||
player = eventreplay.EventPlayer(eventfile, variables)
|
||||
player = EventPlayer(eventfile, variables)
|
||||
|
||||
return toasterui.main(player, player, params)
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"version": 1,
|
||||
"loggers": {
|
||||
"BitBake.SigGen.HashEquiv": {
|
||||
"level": "VERBOSE",
|
||||
"handlers": ["BitBake.verbconsole"]
|
||||
},
|
||||
"BitBake.RunQueue.HashEquiv": {
|
||||
"level": "VERBOSE",
|
||||
"handlers": ["BitBake.verbconsole"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright (C) 2020 Joshua Watt <JPEWhacker@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
def try_unlink(path):
|
||||
try:
|
||||
os.unlink(path)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
def cleanup():
|
||||
shutil.rmtree("tmp/cache", ignore_errors=True)
|
||||
try_unlink("bitbake-cookerdaemon.log")
|
||||
try_unlink("bitbake.sock")
|
||||
try_unlink("bitbake.lock")
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Bitbake parser torture test",
|
||||
epilog="""
|
||||
A torture test for bitbake's parser. Repeatedly interrupts parsing until
|
||||
bitbake decides to deadlock.
|
||||
""",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not "BUILDDIR" in os.environ:
|
||||
print(
|
||||
"'BUILDDIR' not found in the environment. Did you initialize the build environment?"
|
||||
)
|
||||
return 1
|
||||
|
||||
os.chdir(os.environ["BUILDDIR"])
|
||||
|
||||
run_num = 0
|
||||
while True:
|
||||
if run_num % 100 == 0:
|
||||
print("Calibrating wait time...")
|
||||
cleanup()
|
||||
|
||||
start_time = time.monotonic()
|
||||
r = subprocess.run(["bitbake", "-p"])
|
||||
max_wait_time = time.monotonic() - start_time
|
||||
|
||||
if r.returncode != 0:
|
||||
print("Calibration run exited with %d" % r.returncode)
|
||||
return 1
|
||||
|
||||
print("Maximum wait time is %f seconds" % max_wait_time)
|
||||
|
||||
run_num += 1
|
||||
wait_time = random.random() * max_wait_time
|
||||
|
||||
print("Run #%d" % run_num)
|
||||
print("Will sleep for %f seconds" % wait_time)
|
||||
|
||||
cleanup()
|
||||
with subprocess.Popen(["bitbake", "-p"]) as proc:
|
||||
time.sleep(wait_time)
|
||||
proc.send_signal(signal.SIGINT)
|
||||
try:
|
||||
proc.wait(45)
|
||||
except subprocess.TimeoutExpired:
|
||||
print("Run #%d: Waited too long. Possible deadlock!" % run_num)
|
||||
proc.wait()
|
||||
return 1
|
||||
|
||||
if proc.returncode == 0:
|
||||
print("Exited successfully. Timeout too long?")
|
||||
else:
|
||||
print("Exited with %d" % proc.returncode)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,4 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
#
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright (c) 2021 Joshua Watt <JPEWhacker@gmail.com>
|
||||
#
|
||||
# Dockerfile to build a bitbake hash equivalence server container
|
||||
#
|
||||
# From the root of the bitbake repository, run:
|
||||
#
|
||||
# docker build -f contrib/hashserv/Dockerfile .
|
||||
#
|
||||
|
||||
FROM alpine:3.13.1
|
||||
|
||||
RUN apk add --no-cache python3
|
||||
|
||||
COPY bin/bitbake-hashserv /opt/bbhashserv/bin/
|
||||
COPY lib/hashserv /opt/bbhashserv/lib/hashserv/
|
||||
COPY lib/bb /opt/bbhashserv/lib/bb/
|
||||
COPY lib/codegen.py /opt/bbhashserv/lib/codegen.py
|
||||
COPY lib/ply /opt/bbhashserv/lib/ply/
|
||||
COPY lib/bs4 /opt/bbhashserv/lib/bs4/
|
||||
|
||||
ENTRYPOINT ["/opt/bbhashserv/bin/bitbake-hashserv"]
|
||||
@@ -1,62 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright (c) 2022 Daniel Gomez <daniel@qtec.com>
|
||||
#
|
||||
# Dockerfile to build a bitbake PR service container
|
||||
#
|
||||
# From the root of the bitbake repository, run:
|
||||
#
|
||||
# docker build -f contrib/prserv/Dockerfile . -t prserv
|
||||
#
|
||||
# Running examples:
|
||||
#
|
||||
# 1. PR Service in RW mode, port 18585:
|
||||
#
|
||||
# docker run --detach --tty \
|
||||
# --env PORT=18585 \
|
||||
# --publish 18585:18585 \
|
||||
# --volume $PWD:/var/lib/bbprserv \
|
||||
# prserv
|
||||
#
|
||||
# 2. PR Service in RO mode, default port (8585) and custom LOGFILE:
|
||||
#
|
||||
# docker run --detach --tty \
|
||||
# --env DBMODE="--read-only" \
|
||||
# --env LOGFILE=/var/lib/bbprserv/prservro.log \
|
||||
# --publish 8585:8585 \
|
||||
# --volume $PWD:/var/lib/bbprserv \
|
||||
# prserv
|
||||
#
|
||||
|
||||
FROM alpine:3.14.4
|
||||
|
||||
RUN apk add --no-cache python3
|
||||
|
||||
COPY bin/bitbake-prserv /opt/bbprserv/bin/
|
||||
COPY lib/prserv /opt/bbprserv/lib/prserv/
|
||||
COPY lib/bb /opt/bbprserv/lib/bb/
|
||||
COPY lib/codegen.py /opt/bbprserv/lib/codegen.py
|
||||
COPY lib/ply /opt/bbprserv/lib/ply/
|
||||
COPY lib/bs4 /opt/bbprserv/lib/bs4/
|
||||
|
||||
ENV PATH=$PATH:/opt/bbprserv/bin
|
||||
|
||||
RUN mkdir -p /var/lib/bbprserv
|
||||
|
||||
ENV DBFILE=/var/lib/bbprserv/prserv.sqlite3 \
|
||||
LOGFILE=/var/lib/bbprserv/prserv.log \
|
||||
LOGLEVEL=debug \
|
||||
HOST=0.0.0.0 \
|
||||
PORT=8585 \
|
||||
DBMODE=""
|
||||
|
||||
ENTRYPOINT [ "/bin/sh", "-c", \
|
||||
"bitbake-prserv \
|
||||
--file=$DBFILE \
|
||||
--log=$LOGFILE \
|
||||
--loglevel=$LOGLEVEL \
|
||||
--start \
|
||||
--host=$HOST \
|
||||
--port=$PORT \
|
||||
$DBMODE \
|
||||
&& tail -f $LOGFILE"]
|
||||
@@ -1,18 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -6,12 +6,12 @@
|
||||
"
|
||||
" This sets up the syntax highlighting for BitBake files, like .bb, .bbclass and .inc
|
||||
|
||||
if &compatible || version < 600 || exists("b:loaded_bitbake_plugin")
|
||||
if &compatible || version < 600
|
||||
finish
|
||||
endif
|
||||
|
||||
" .bb, .bbappend and .bbclass
|
||||
au BufNewFile,BufRead *.{bb,bbappend,bbclass} set filetype=bitbake
|
||||
au BufNewFile,BufRead *.{bb,bbappend,bbclass} set filetype=bitbake
|
||||
|
||||
" .inc
|
||||
au BufNewFile,BufRead *.inc set filetype=bitbake
|
||||
|
||||
@@ -1,13 +1,2 @@
|
||||
" Only do this when not done yet for this buffer
|
||||
if exists("b:did_ftplugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
" Don't load another plugin for this buffer
|
||||
let b:did_ftplugin = 1
|
||||
|
||||
let b:undo_ftplugin = "setl cms< sts< sw< et< sua<"
|
||||
|
||||
setlocal commentstring=#\ %s
|
||||
setlocal softtabstop=4 shiftwidth=4 expandtab
|
||||
setlocal suffixesadd+=.bb,.bbclass
|
||||
set sts=4 sw=4 et
|
||||
set cms=#%s
|
||||
|
||||
@@ -1,343 +0,0 @@
|
||||
" Vim indent file
|
||||
" Language: BitBake
|
||||
" Copyright: Copyright (C) 2019 Agilent Technologies, Inc.
|
||||
" Maintainer: Chris Laplante <chris.laplante@agilent.com>
|
||||
" License: You may redistribute this under the same terms as Vim itself
|
||||
|
||||
|
||||
if exists("b:did_indent")
|
||||
finish
|
||||
endif
|
||||
|
||||
if exists("*BitbakeIndent")
|
||||
finish
|
||||
endif
|
||||
|
||||
runtime! indent/sh.vim
|
||||
unlet b:did_indent
|
||||
|
||||
setlocal indentexpr=BitbakeIndent(v:lnum)
|
||||
setlocal autoindent nolisp
|
||||
|
||||
function s:is_bb_python_func_def(lnum)
|
||||
let stack = synstack(a:lnum, 1)
|
||||
if len(stack) == 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
let top = synIDattr(stack[0], "name")
|
||||
echo top
|
||||
|
||||
return synIDattr(stack[0], "name") == "bbPyFuncDef"
|
||||
endfunction
|
||||
|
||||
"""" begin modified from indent/python.vim, upstream commit 7a9bd7c1e0ce1baf5a02daf36eeae3638aa315c7
|
||||
"""" This copied code is licensed the same as Vim itself.
|
||||
setlocal indentkeys+=<:>,=elif,=except
|
||||
|
||||
let s:keepcpo= &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:maxoff = 50 " maximum number of lines to look backwards for ()
|
||||
|
||||
function! GetBBPythonIndent(lnum)
|
||||
|
||||
" If this line is explicitly joined: If the previous line was also joined,
|
||||
" line it up with that one, otherwise add two 'shiftwidth'
|
||||
if getline(a:lnum - 1) =~ '\\$'
|
||||
if a:lnum > 1 && getline(a:lnum - 2) =~ '\\$'
|
||||
return indent(a:lnum - 1)
|
||||
endif
|
||||
return indent(a:lnum - 1) + (exists("g:pyindent_continue") ? eval(g:pyindent_continue) : (shiftwidth() * 2))
|
||||
endif
|
||||
|
||||
" If the start of the line is in a string don't change the indent.
|
||||
if has('syntax_items')
|
||||
\ && synIDattr(synID(a:lnum, 1, 1), "name") =~ "String$"
|
||||
return -1
|
||||
endif
|
||||
|
||||
" Search backwards for the previous non-empty line.
|
||||
let plnum = prevnonblank(v:lnum - 1)
|
||||
|
||||
if plnum == 0
|
||||
" This is the first non-empty line, use zero indent.
|
||||
return 0
|
||||
endif
|
||||
|
||||
call cursor(plnum, 1)
|
||||
|
||||
" Identing inside parentheses can be very slow, regardless of the searchpair()
|
||||
" timeout, so let the user disable this feature if he doesn't need it
|
||||
let disable_parentheses_indenting = get(g:, "pyindent_disable_parentheses_indenting", 0)
|
||||
|
||||
if disable_parentheses_indenting == 1
|
||||
let plindent = indent(plnum)
|
||||
let plnumstart = plnum
|
||||
else
|
||||
" searchpair() can be slow sometimes, limit the time to 150 msec or what is
|
||||
" put in g:pyindent_searchpair_timeout
|
||||
let searchpair_stopline = 0
|
||||
let searchpair_timeout = get(g:, 'pyindent_searchpair_timeout', 150)
|
||||
|
||||
" If the previous line is inside parenthesis, use the indent of the starting
|
||||
" line.
|
||||
" Trick: use the non-existing "dummy" variable to break out of the loop when
|
||||
" going too far back.
|
||||
let parlnum = searchpair('(\|{\|\[', '', ')\|}\|\]', 'nbW',
|
||||
\ "line('.') < " . (plnum - s:maxoff) . " ? dummy :"
|
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
|
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
|
||||
\ searchpair_stopline, searchpair_timeout)
|
||||
if parlnum > 0
|
||||
" We may have found the opening brace of a BitBake Python task, e.g. 'python do_task {'
|
||||
" If so, ignore it here - it will be handled later.
|
||||
if s:is_bb_python_func_def(parlnum)
|
||||
let parlnum = 0
|
||||
let plindent = indent(plnum)
|
||||
let plnumstart = plnum
|
||||
else
|
||||
let plindent = indent(parlnum)
|
||||
let plnumstart = parlnum
|
||||
endif
|
||||
else
|
||||
let plindent = indent(plnum)
|
||||
let plnumstart = plnum
|
||||
endif
|
||||
|
||||
" When inside parenthesis: If at the first line below the parenthesis add
|
||||
" two 'shiftwidth', otherwise same as previous line.
|
||||
" i = (a
|
||||
" + b
|
||||
" + c)
|
||||
call cursor(a:lnum, 1)
|
||||
let p = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
|
||||
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
|
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
|
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
|
||||
\ searchpair_stopline, searchpair_timeout)
|
||||
if p > 0
|
||||
if s:is_bb_python_func_def(p)
|
||||
" Handle first non-empty line inside a BB Python task
|
||||
if p == plnum
|
||||
return shiftwidth()
|
||||
endif
|
||||
|
||||
" Handle the user actually trying to close a BitBake Python task
|
||||
let line = getline(a:lnum)
|
||||
if line =~ '^\s*}'
|
||||
return -2
|
||||
endif
|
||||
|
||||
" Otherwise ignore the brace
|
||||
let p = 0
|
||||
else
|
||||
if p == plnum
|
||||
" When the start is inside parenthesis, only indent one 'shiftwidth'.
|
||||
let pp = searchpair('(\|{\|\[', '', ')\|}\|\]', 'bW',
|
||||
\ "line('.') < " . (a:lnum - s:maxoff) . " ? dummy :"
|
||||
\ . " synIDattr(synID(line('.'), col('.'), 1), 'name')"
|
||||
\ . " =~ '\\(Comment\\|Todo\\|String\\)$'",
|
||||
\ searchpair_stopline, searchpair_timeout)
|
||||
if pp > 0
|
||||
return indent(plnum) + (exists("g:pyindent_nested_paren") ? eval(g:pyindent_nested_paren) : shiftwidth())
|
||||
endif
|
||||
return indent(plnum) + (exists("g:pyindent_open_paren") ? eval(g:pyindent_open_paren) : (shiftwidth() * 2))
|
||||
endif
|
||||
if plnumstart == p
|
||||
return indent(plnum)
|
||||
endif
|
||||
return plindent
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
" Get the line and remove a trailing comment.
|
||||
" Use syntax highlighting attributes when possible.
|
||||
let pline = getline(plnum)
|
||||
let pline_len = strlen(pline)
|
||||
if has('syntax_items')
|
||||
" If the last character in the line is a comment, do a binary search for
|
||||
" the start of the comment. synID() is slow, a linear search would take
|
||||
" too long on a long line.
|
||||
if synIDattr(synID(plnum, pline_len, 1), "name") =~ "\\(Comment\\|Todo\\)$"
|
||||
let min = 1
|
||||
let max = pline_len
|
||||
while min < max
|
||||
let col = (min + max) / 2
|
||||
if synIDattr(synID(plnum, col, 1), "name") =~ "\\(Comment\\|Todo\\)$"
|
||||
let max = col
|
||||
else
|
||||
let min = col + 1
|
||||
endif
|
||||
endwhile
|
||||
let pline = strpart(pline, 0, min - 1)
|
||||
endif
|
||||
else
|
||||
let col = 0
|
||||
while col < pline_len
|
||||
if pline[col] == '#'
|
||||
let pline = strpart(pline, 0, col)
|
||||
break
|
||||
endif
|
||||
let col = col + 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
" If the previous line ended with a colon, indent this line
|
||||
if pline =~ ':\s*$'
|
||||
return plindent + shiftwidth()
|
||||
endif
|
||||
|
||||
" If the previous line was a stop-execution statement...
|
||||
" TODO: utilize this logic to deindent when ending a bbPyDefRegion
|
||||
if getline(plnum) =~ '^\s*\(break\|continue\|raise\|return\|pass\|bb\.fatal\)\>'
|
||||
" See if the user has already dedented
|
||||
if indent(a:lnum) > indent(plnum) - shiftwidth()
|
||||
" If not, recommend one dedent
|
||||
return indent(plnum) - shiftwidth()
|
||||
endif
|
||||
" Otherwise, trust the user
|
||||
return -1
|
||||
endif
|
||||
|
||||
" If the current line begins with a keyword that lines up with "try"
|
||||
if getline(a:lnum) =~ '^\s*\(except\|finally\)\>'
|
||||
let lnum = a:lnum - 1
|
||||
while lnum >= 1
|
||||
if getline(lnum) =~ '^\s*\(try\|except\)\>'
|
||||
let ind = indent(lnum)
|
||||
if ind >= indent(a:lnum)
|
||||
return -1 " indent is already less than this
|
||||
endif
|
||||
return ind " line up with previous try or except
|
||||
endif
|
||||
let lnum = lnum - 1
|
||||
endwhile
|
||||
return -1 " no matching "try"!
|
||||
endif
|
||||
|
||||
" If the current line begins with a header keyword, dedent
|
||||
if getline(a:lnum) =~ '^\s*\(elif\|else\)\>'
|
||||
|
||||
" Unless the previous line was a one-liner
|
||||
if getline(plnumstart) =~ '^\s*\(for\|if\|try\)\>'
|
||||
return plindent
|
||||
endif
|
||||
|
||||
" Or the user has already dedented
|
||||
if indent(a:lnum) <= plindent - shiftwidth()
|
||||
return -1
|
||||
endif
|
||||
|
||||
return plindent - shiftwidth()
|
||||
endif
|
||||
|
||||
" When after a () construct we probably want to go back to the start line.
|
||||
" a = (b
|
||||
" + c)
|
||||
" here
|
||||
if parlnum > 0
|
||||
return plindent
|
||||
endif
|
||||
|
||||
return -1
|
||||
|
||||
endfunction
|
||||
|
||||
let &cpo = s:keepcpo
|
||||
unlet s:keepcpo
|
||||
|
||||
""" end of stuff from indent/python.vim
|
||||
|
||||
|
||||
let b:did_indent = 1
|
||||
setlocal indentkeys+=0\"
|
||||
|
||||
|
||||
function! BitbakeIndent(lnum)
|
||||
if !has('syntax_items')
|
||||
return -1
|
||||
endif
|
||||
|
||||
let stack = synstack(a:lnum, 1)
|
||||
if len(stack) == 0
|
||||
return -1
|
||||
endif
|
||||
|
||||
let name = synIDattr(stack[0], "name")
|
||||
|
||||
" TODO: support different styles of indentation for assignments. For now,
|
||||
" we only support like this:
|
||||
" VAR = " \
|
||||
" value1 \
|
||||
" value2 \
|
||||
" "
|
||||
"
|
||||
" i.e. each value indented by shiftwidth(), with the final quote " completely unindented.
|
||||
if name == "bbVarValue"
|
||||
" Quote handling is tricky. kernel.bbclass has this line for instance:
|
||||
" EXTRA_OEMAKE = " HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}" " HOSTCPP="${BUILD_CPP}""
|
||||
" Instead of trying to handle crazy cases like that, just assume that a
|
||||
" double-quote on a line by itself (following an assignment) means the
|
||||
" user is closing the assignment, and de-dent.
|
||||
if getline(a:lnum) =~ '^\s*"$'
|
||||
return 0
|
||||
endif
|
||||
|
||||
let prevstack = synstack(a:lnum - 1, 1)
|
||||
if len(prevstack) == 0
|
||||
return -1
|
||||
endif
|
||||
|
||||
let prevname = synIDattr(prevstack[0], "name")
|
||||
|
||||
" Only indent if there was actually a continuation character on
|
||||
" the previous line, to avoid misleading indentation.
|
||||
let prevlinelastchar = synIDattr(synID(a:lnum - 1, col([a:lnum - 1, "$"]) - 1, 1), "name")
|
||||
let prev_continued = prevlinelastchar == "bbContinue"
|
||||
|
||||
" Did the previous line introduce an assignment?
|
||||
if index(["bbVarDef", "bbVarFlagDef"], prevname) != -1
|
||||
if prev_continued
|
||||
return shiftwidth()
|
||||
endif
|
||||
endif
|
||||
|
||||
if !prev_continued
|
||||
return 0
|
||||
endif
|
||||
|
||||
" Autoindent can take it from here
|
||||
return -1
|
||||
endif
|
||||
|
||||
if index(["bbPyDefRegion", "bbPyFuncRegion"], name) != -1
|
||||
let ret = GetBBPythonIndent(a:lnum)
|
||||
" Should normally always be indented by at least one shiftwidth; but allow
|
||||
" return of -1 (defer to autoindent) or -2 (force indent to 0)
|
||||
if ret == 0
|
||||
return shiftwidth()
|
||||
elseif ret == -2
|
||||
return 0
|
||||
endif
|
||||
return ret
|
||||
endif
|
||||
|
||||
" TODO: GetShIndent doesn't detect tasks prepended with 'fakeroot'
|
||||
" Need to submit a patch upstream to Vim to provide an extension point.
|
||||
" Unlike the Python indenter, the Sh indenter is way too large to copy and
|
||||
" modify here.
|
||||
if name == "bbShFuncRegion"
|
||||
return GetShIndent()
|
||||
endif
|
||||
|
||||
" TODO:
|
||||
" + heuristics for de-denting out of a bbPyDefRegion? e.g. when the user
|
||||
" types an obvious BB keyword like addhandler or addtask, or starts
|
||||
" writing a shell task. Maybe too hard to implement...
|
||||
|
||||
return -1
|
||||
endfunction
|
||||
14
bitbake/contrib/vim/plugin/newbb.vim
Normal file → Executable file
14
bitbake/contrib/vim/plugin/newbb.vim
Normal file → Executable file
@@ -10,7 +10,7 @@
|
||||
"
|
||||
" Will try to use git to find the user name and email
|
||||
|
||||
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
|
||||
if &compatible || v:version < 600
|
||||
finish
|
||||
endif
|
||||
|
||||
@@ -25,7 +25,7 @@ endfun
|
||||
fun! <SID>GetUserEmail()
|
||||
let l:user_email = system("git config --get user.email")
|
||||
if v:shell_error
|
||||
return "unknown@user.org"
|
||||
return "unknow@user.org"
|
||||
else
|
||||
return substitute(l:user_email, "\n", "", "")
|
||||
endfun
|
||||
@@ -41,10 +41,6 @@ fun! BBHeader()
|
||||
endfun
|
||||
|
||||
fun! NewBBTemplate()
|
||||
if line2byte(line('$') + 1) != -1
|
||||
return
|
||||
endif
|
||||
|
||||
let l:paste = &paste
|
||||
set nopaste
|
||||
|
||||
@@ -52,7 +48,7 @@ fun! NewBBTemplate()
|
||||
call BBHeader()
|
||||
|
||||
" New the bb template
|
||||
put ='SUMMARY = \"\"'
|
||||
put ='DESCRIPTION = \"\"'
|
||||
put ='HOMEPAGE = \"\"'
|
||||
put ='LICENSE = \"\"'
|
||||
put ='SECTION = \"\"'
|
||||
@@ -62,7 +58,7 @@ fun! NewBBTemplate()
|
||||
|
||||
" Go to the first place to edit
|
||||
0
|
||||
/^SUMMARY =/
|
||||
/^DESCRIPTION =/
|
||||
exec "normal 2f\""
|
||||
|
||||
if paste == 1
|
||||
@@ -80,7 +76,7 @@ if v:progname =~ "vimdiff"
|
||||
endif
|
||||
|
||||
augroup NewBB
|
||||
au BufNewFile,BufReadPost *.bb
|
||||
au BufNewFile *.bb
|
||||
\ if g:bb_create_on_empty |
|
||||
\ call NewBBTemplate() |
|
||||
\ endif
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
" Vim plugin file
|
||||
" Purpose: Create a template for new bbappend file
|
||||
" Author: Joshua Watt <JPEWhacker@gmail.com>
|
||||
" Copyright: Copyright (C) 2017 Joshua Watt <JPEWhacker@gmail.com>
|
||||
"
|
||||
" This file is licensed under the MIT license, see COPYING.MIT in
|
||||
" this source distribution for the terms.
|
||||
"
|
||||
|
||||
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
|
||||
finish
|
||||
endif
|
||||
|
||||
fun! NewBBAppendTemplate()
|
||||
if line2byte(line('$') + 1) != -1
|
||||
return
|
||||
endif
|
||||
|
||||
let l:paste = &paste
|
||||
set nopaste
|
||||
|
||||
" New bbappend template
|
||||
0 put ='FILESEXTRAPATHS:prepend := \"${THISDIR}/${PN}:\"'
|
||||
2
|
||||
|
||||
if paste == 1
|
||||
set paste
|
||||
endif
|
||||
endfun
|
||||
|
||||
if !exists("g:bb_create_on_empty")
|
||||
let g:bb_create_on_empty = 1
|
||||
endif
|
||||
|
||||
" disable in case of vimdiff
|
||||
if v:progname =~ "vimdiff"
|
||||
let g:bb_create_on_empty = 0
|
||||
endif
|
||||
|
||||
augroup NewBBAppend
|
||||
au BufNewFile,BufReadPost *.bbappend
|
||||
\ if g:bb_create_on_empty |
|
||||
\ call NewBBAppendTemplate() |
|
||||
\ endif
|
||||
augroup END
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"
|
||||
" It's an entirely new type, just has specific syntax in shell and python code
|
||||
|
||||
if &compatible || v:version < 600 || exists("b:loaded_bitbake_plugin")
|
||||
if &compatible || v:version < 600
|
||||
finish
|
||||
endif
|
||||
if exists("b:current_syntax")
|
||||
@@ -51,34 +51,31 @@ syn region bbString matchgroup=bbQuote start=+'+ skip=+\\$+ end=+'+
|
||||
syn match bbExport "^export" nextgroup=bbIdentifier skipwhite
|
||||
syn keyword bbExportFlag export contained nextgroup=bbIdentifier skipwhite
|
||||
syn match bbIdentifier "[a-zA-Z0-9\-_\.\/\+]\+" display contained
|
||||
syn match bbVarDeref "${[a-zA-Z0-9\-_:\.\/\+]\+}" contained
|
||||
syn match bbVarDeref "${[a-zA-Z0-9\-_\.\/\+]\+}" contained
|
||||
syn match bbVarEq "\(:=\|+=\|=+\|\.=\|=\.\|?=\|??=\|=\)" contained nextgroup=bbVarValue
|
||||
syn match bbVarDef "^\(export\s*\)\?\([a-zA-Z0-9\-_\.\/\+][${}a-zA-Z0-9\-_:\.\/\+]*\)\s*\(:=\|+=\|=+\|\.=\|=\.\|?=\|??=\|=\)\@=" contains=bbExportFlag,bbIdentifier,bbOverrideOperator,bbVarDeref nextgroup=bbVarEq
|
||||
syn match bbVarDef "^\(export\s*\)\?\([a-zA-Z0-9\-_\.\/\+]\+\(_[${}a-zA-Z0-9\-_\.\/\+]\+\)\?\)\s*\(:=\|+=\|=+\|\.=\|=\.\|?=\|??=\|=\)\@=" contains=bbExportFlag,bbIdentifier,bbVarDeref nextgroup=bbVarEq
|
||||
syn match bbVarValue ".*$" contained contains=bbString,bbVarDeref,bbVarPyValue
|
||||
syn region bbVarPyValue start=+${@+ skip=+\\$+ end=+}+ contained contains=@python
|
||||
|
||||
" Vars metadata flags
|
||||
syn match bbVarFlagDef "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.+]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
|
||||
syn region bbVarFlagFlag matchgroup=bbArrayBrackets start="\[" end="\]\s*\(:=\|=\|.=\|=.|+=\|=+\|?=\)\@=" contained contains=bbIdentifier nextgroup=bbVarEq
|
||||
syn match bbVarFlagDef "^\([a-zA-Z0-9\-_\.]\+\)\(\[[a-zA-Z0-9\-_\.]\+\]\)\@=" contains=bbIdentifier nextgroup=bbVarFlagFlag
|
||||
syn region bbVarFlagFlag matchgroup=bbArrayBrackets start="\[" end="\]\s*\(=\|+=\|=+\|?=\)\@=" contained contains=bbIdentifier nextgroup=bbVarEq
|
||||
|
||||
" Includes and requires
|
||||
syn keyword bbInclude inherit include require contained
|
||||
syn match bbIncludeRest ".*$" contained contains=bbString,bbVarDeref,bbVarPyValue
|
||||
syn match bbIncludeRest ".*$" contained contains=bbString,bbVarDeref
|
||||
syn match bbIncludeLine "^\(inherit\|include\|require\)\s\+" contains=bbInclude nextgroup=bbIncludeRest
|
||||
|
||||
" Add taks and similar
|
||||
syn keyword bbStatement addtask deltask addhandler after before EXPORT_FUNCTIONS contained
|
||||
syn match bbStatementRest /[^\\]*$/ skipwhite contained contains=bbStatement,bbVarDeref,bbVarPyValue
|
||||
syn region bbStatementRestCont start=/.*\\$/ end=/^[^\\]*$/ contained contains=bbStatement,bbVarDeref,bbVarPyValue,bbContinue keepend
|
||||
syn match bbStatementLine "^\(addtask\|deltask\|addhandler\|after\|before\|EXPORT_FUNCTIONS\)\s\+" contains=bbStatement nextgroup=bbStatementRest,bbStatementRestCont
|
||||
syn keyword bbStatement addtask addhandler after before EXPORT_FUNCTIONS contained
|
||||
syn match bbStatementRest ".*$" skipwhite contained contains=bbStatement
|
||||
syn match bbStatementLine "^\(addtask\|addhandler\|after\|before\|EXPORT_FUNCTIONS\)\s\+" contains=bbStatement nextgroup=bbStatementRest
|
||||
|
||||
" OE Important Functions
|
||||
syn keyword bbOEFunctions do_fetch do_unpack do_patch do_configure do_compile do_stage do_install do_package contained
|
||||
|
||||
" Generic Functions
|
||||
syn match bbFunction "\h[0-9A-Za-z_\-\.]*" display contained contains=bbOEFunctions
|
||||
|
||||
syn keyword bbOverrideOperator append prepend remove contained
|
||||
syn match bbFunction "\h[0-9A-Za-z_-]*" display contained contains=bbOEFunctions
|
||||
|
||||
" BitBake shell metadata
|
||||
syn include @shell syntax/sh.vim
|
||||
@@ -86,7 +83,7 @@ if exists("b:current_syntax")
|
||||
unlet b:current_syntax
|
||||
endif
|
||||
syn keyword bbShFakeRootFlag fakeroot contained
|
||||
syn match bbShFuncDef "^\(fakeroot\s*\)\?\([\.0-9A-Za-z_:${}\-\.]\+\)\(python\)\@<!\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbFunction,bbOverrideOperator,bbVarDeref,bbDelimiter nextgroup=bbShFuncRegion skipwhite
|
||||
syn match bbShFuncDef "^\(fakeroot\s*\)\?\([0-9A-Za-z_${}-]\+\)\(python\)\@<!\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbShFuncRegion skipwhite
|
||||
syn region bbShFuncRegion matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@shell
|
||||
|
||||
" Python value inside shell functions
|
||||
@@ -94,7 +91,7 @@ syn region shDeref start=+${@+ skip=+\\$+ excludenl end=+}+ contained co
|
||||
|
||||
" BitBake python metadata
|
||||
syn keyword bbPyFlag python contained
|
||||
syn match bbPyFuncDef "^\(fakeroot\s*\)\?\(python\)\(\s\+[0-9A-Za-z_:${}\-\.]\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbShFakeRootFlag,bbPyFlag,bbFunction,bbOverrideOperator,bbVarDeref,bbDelimiter nextgroup=bbPyFuncRegion skipwhite
|
||||
syn match bbPyFuncDef "^\(python\s\+\)\([0-9A-Za-z_${}-]\+\)\?\(\s*()\s*\)\({\)\@=" contains=bbPyFlag,bbFunction,bbVarDeref,bbDelimiter nextgroup=bbPyFuncRegion skipwhite
|
||||
syn region bbPyFuncRegion matchgroup=bbDelimiter start="{\s*$" end="^}\s*$" contained contains=@python
|
||||
|
||||
" BitBake 'def'd python functions
|
||||
@@ -123,9 +120,7 @@ hi def link bbPyFlag Type
|
||||
hi def link bbPyDef Statement
|
||||
hi def link bbStatement Statement
|
||||
hi def link bbStatementRest Identifier
|
||||
hi def link bbStatementRestCont Identifier
|
||||
hi def link bbOEFunctions Special
|
||||
hi def link bbVarPyValue PreProc
|
||||
hi def link bbOverrideOperator Operator
|
||||
|
||||
let b:current_syntax = "bb"
|
||||
|
||||
1
bitbake/doc/.gitignore
vendored
1
bitbake/doc/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
_build/
|
||||
@@ -1,35 +1,91 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
# This is a single Makefile to handle all generated BitBake documents.
|
||||
# The Makefile needs to live in the documentation directory and all figures used
|
||||
# in any manuals must be .PNG files and live in the individual book's figures
|
||||
# directory.
|
||||
#
|
||||
# The Makefile has these targets:
|
||||
#
|
||||
# pdf: generates a PDF version of a manual.
|
||||
# html: generates an HTML version of a manual.
|
||||
# tarball: creates a tarball for the doc files.
|
||||
# validate: validates
|
||||
# clean: removes files
|
||||
#
|
||||
# The Makefile generates an HTML version of every document. The
|
||||
# variable DOC indicates the folder name for a given manual.
|
||||
#
|
||||
# To build a manual, you must invoke 'make' with the DOC argument.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# make DOC=bitbake-user-manual
|
||||
# make pdf DOC=bitbake-user-manual
|
||||
#
|
||||
# The first example generates the HTML version of the User Manual.
|
||||
# The second example generates the PDF version of the User Manual.
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?= -W --keep-going -j auto
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
DESTDIR = final
|
||||
ifeq ($(DOC),bitbake-user-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet bitbake-user-manual-style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html tarball
|
||||
TARFILES = bitbake-user-manual-style.css bitbake-user-manual.html figures/bitbake-title.png
|
||||
MANUALS = $(DOC)/$(DOC).html
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
|
||||
ifeq ($(shell if which $(SPHINXBUILD) >/dev/null 2>&1; then echo 1; else echo 0; fi),0)
|
||||
$(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed")
|
||||
endif
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
##
|
||||
# These URI should be rewritten by your distribution's xml catalog to
|
||||
# match your localy installed XSL stylesheets.
|
||||
XSL_BASE_URI = http://docbook.sourceforge.net/release/xsl/current
|
||||
XSL_XHTML_URI = $(XSL_BASE_URI)/xhtml/docbook.xsl
|
||||
|
||||
.PHONY: help Makefile clean publish
|
||||
all: $(ALLPREQ)
|
||||
|
||||
publish: Makefile html singlehtml
|
||||
rm -rf $(BUILDDIR)/$(DESTDIR)/
|
||||
mkdir -p $(BUILDDIR)/$(DESTDIR)/
|
||||
cp -r $(BUILDDIR)/html/* $(BUILDDIR)/$(DESTDIR)/
|
||||
cp $(BUILDDIR)/singlehtml/index.html $(BUILDDIR)/$(DESTDIR)/singleindex.html
|
||||
sed -i -e 's@index.html#@singleindex.html#@g' $(BUILDDIR)/$(DESTDIR)/singleindex.html
|
||||
pdf:
|
||||
ifeq ($(DOC),bitbake-user-manual)
|
||||
@echo " "
|
||||
@echo "********** Building."$(DOC)
|
||||
@echo " "
|
||||
cd $(DOC); ../tools/docbook-to-pdf $(DOC).xml ../template; cd ..
|
||||
endif
|
||||
|
||||
html:
|
||||
ifeq ($(DOC),bitbake-user-manual)
|
||||
# See http://www.sagehill.net/docbookxsl/HtmlOutput.html
|
||||
@echo " "
|
||||
@echo "******** Building "$(DOC)
|
||||
@echo " "
|
||||
cd $(DOC); xsltproc $(XSLTOPTS) -o $(DOC).html $(DOC)-customization.xsl $(DOC).xml; cd ..
|
||||
endif
|
||||
|
||||
tarball: html
|
||||
@echo " "
|
||||
@echo "******** Creating Tarball of document files"
|
||||
@echo " "
|
||||
cd $(DOC); tar -cvzf $(DOC).tgz $(TARFILES); cd ..
|
||||
|
||||
validate:
|
||||
cd $(DOC); xmllint --postvalid --xinclude --noout $(DOC).xml; cd ..
|
||||
|
||||
publish:
|
||||
@if test -f $(DOC)/$(DOC).html; \
|
||||
then \
|
||||
echo " "; \
|
||||
echo "******** Publishing "$(DOC)".html"; \
|
||||
echo " "; \
|
||||
scp -r $(MANUALS) $(STYLESHEET) docs.yp:/var/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
|
||||
cd $(DOC); scp -r $(FIGURES) docs.yp:/var/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
|
||||
else \
|
||||
echo " "; \
|
||||
echo $(DOC)".html missing. Generate the file first then try again."; \
|
||||
echo " "; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
@rm -rf $(BUILDDIR)
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
rm -rf $(MANUALS); rm $(DOC)/$(DOC).tgz;
|
||||
|
||||
@@ -8,48 +8,32 @@ Manual Organization
|
||||
|
||||
Folders exist for individual manuals as follows:
|
||||
|
||||
* bitbake-user-manual --- The BitBake User Manual
|
||||
* bitbake-user-manual - The BitBake User Manual
|
||||
|
||||
Each folder is self-contained regarding content and figures.
|
||||
|
||||
If you want to find HTML versions of the BitBake manuals on the web,
|
||||
go to https://www.openembedded.org/wiki/Documentation.
|
||||
go to http://www.openembedded.org/wiki/Documentation.
|
||||
|
||||
Sphinx
|
||||
======
|
||||
Makefile
|
||||
========
|
||||
|
||||
The BitBake documentation was migrated from the original DocBook
|
||||
format to Sphinx based documentation for the Yocto Project 3.2
|
||||
release.
|
||||
The Makefile processes manual directories to create HTML, PDF,
|
||||
tarballs, etc. Details on how the Makefile work are documented
|
||||
inside the Makefile. See that file for more information.
|
||||
|
||||
Additional information related to the Sphinx migration, and guidelines
|
||||
for developers willing to contribute to the BitBake documentation can
|
||||
be found in the Yocto Project Documentation README file:
|
||||
To build a manual, you run the make command and pass it the name
|
||||
of the folder containing the manual's contents.
|
||||
For example, the following command run from the documentation directory
|
||||
creates an HTML and a PDF version of the BitBake User Manual.
|
||||
The DOC variable specifies the manual you are making:
|
||||
|
||||
https://git.yoctoproject.org/cgit/cgit.cgi/yocto-docs/tree/documentation/README
|
||||
$ make DOC=bitbake-user-manual
|
||||
|
||||
How to build the Yocto Project documentation
|
||||
============================================
|
||||
template
|
||||
========
|
||||
Contains various templates, fonts, and some old PNG files.
|
||||
|
||||
Sphinx is written in Python. While it might work with Python2, for
|
||||
obvious reasons, we will only support building the BitBake
|
||||
documentation with Python3.
|
||||
|
||||
Sphinx might be available in your Linux distro packages repositories,
|
||||
however it is not recommend using distro packages, as they might be
|
||||
old versions, especially if you are using an LTS version of your
|
||||
distro. The recommended method to install Sphinx and all required
|
||||
dependencies is to use the Python Package Index (pip).
|
||||
|
||||
To install all required packages run:
|
||||
|
||||
$ pip3 install sphinx sphinx_rtd_theme pyyaml
|
||||
|
||||
To build the documentation locally, run:
|
||||
|
||||
$ cd doc
|
||||
$ make html
|
||||
|
||||
The resulting HTML index page will be _build/html/index.html, and you
|
||||
can browse your own copy of the locally generated documentation with
|
||||
your browser.
|
||||
tools
|
||||
=====
|
||||
Contains a tool to convert the DocBook files to PDF format.
|
||||
|
||||
14
bitbake/doc/_templates/breadcrumbs.html
vendored
14
bitbake/doc/_templates/breadcrumbs.html
vendored
@@ -1,14 +0,0 @@
|
||||
{% extends "!breadcrumbs.html" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li>
|
||||
<span class="doctype_switcher_placeholder">{{ doctype or 'single' }}</span>
|
||||
<span class="version_switcher_placeholder">{{ release }}</span>
|
||||
</li>
|
||||
<li> »</li>
|
||||
{% for doc in parents %}
|
||||
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> »</li>
|
||||
{% endfor %}
|
||||
<li>{{ title }}</li>
|
||||
{% endblock %}
|
||||
|
||||
9
bitbake/doc/_templates/footer.html
vendored
9
bitbake/doc/_templates/footer.html
vendored
@@ -1,9 +0,0 @@
|
||||
<footer>
|
||||
<hr/>
|
||||
<div role="contentinfo">
|
||||
<p>© Copyright {{ copyright }}
|
||||
<br>Last updated on {{ last_updated }} from the <a href="https://git.openembedded.org/bitbake/">bitbake</a> git repository.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
7
bitbake/doc/_templates/layout.html
vendored
7
bitbake/doc/_templates/layout.html
vendored
@@ -1,7 +0,0 @@
|
||||
{% extends "!layout.html" %}
|
||||
|
||||
{% block extrabody %}
|
||||
<div id="outdated-warning" style="text-align: center; background-color: #FFBABA; color: #6A0E0E;">
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
|
||||
|
||||
<xsl:import href="http://downloads.yoctoproject.org/mirror/docbook-mirror/docbook-xsl-1.76.1/xhtml/docbook.xsl" />
|
||||
|
||||
<!--
|
||||
|
||||
<xsl:import href="../template/1.76.1/docbook-xsl-1.76.1/xhtml/docbook.xsl" />
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/1.76.1/xhtml/docbook.xsl" />
|
||||
|
||||
-->
|
||||
|
||||
<xsl:include href="../template/permalinks.xsl"/>
|
||||
<xsl:include href="../template/section.title.xsl"/>
|
||||
<xsl:include href="../template/component.title.xsl"/>
|
||||
<xsl:include href="../template/division.title.xsl"/>
|
||||
<xsl:include href="../template/formal.object.heading.xsl"/>
|
||||
<xsl:include href="../template/gloss-permalinks.xsl"/>
|
||||
|
||||
<xsl:param name="html.stylesheet" select="'user-manual-style.css'" />
|
||||
<xsl:param name="chapter.autolabel" select="1" />
|
||||
<xsl:param name="section.autolabel" select="1" />
|
||||
<xsl:param name="section.label.includes.component.label" select="1" />
|
||||
<xsl:param name="appendix.autolabel">A</xsl:param>
|
||||
|
||||
<!-- <xsl:param name="generate.toc" select="'article nop'"></xsl:param> -->
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -1,761 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
=========
|
||||
Execution
|
||||
=========
|
||||
|
||||
|
|
||||
|
||||
The primary purpose for running BitBake is to produce some kind of
|
||||
output such as a single installable package, a kernel, a software
|
||||
development kit, or even a full, board-specific bootable Linux image,
|
||||
complete with bootloader, kernel, and root filesystem. Of course, you
|
||||
can execute the ``bitbake`` command with options that cause it to
|
||||
execute single tasks, compile single recipe files, capture or clear
|
||||
data, or simply return information about the execution environment.
|
||||
|
||||
This chapter describes BitBake's execution process from start to finish
|
||||
when you use it to create an image. The execution process is launched
|
||||
using the following command form::
|
||||
|
||||
$ bitbake target
|
||||
|
||||
For information on
|
||||
the BitBake command and its options, see ":ref:`The BitBake Command
|
||||
<bitbake-user-manual-command>`" section.
|
||||
|
||||
.. note::
|
||||
|
||||
Prior to executing BitBake, you should take advantage of available
|
||||
parallel thread execution on your build host by setting the
|
||||
:term:`BB_NUMBER_THREADS` variable in
|
||||
your project's ``local.conf`` configuration file.
|
||||
|
||||
A common method to determine this value for your build host is to run
|
||||
the following::
|
||||
|
||||
$ grep processor /proc/cpuinfo
|
||||
|
||||
This command returns
|
||||
the number of processors, which takes into account hyper-threading.
|
||||
Thus, a quad-core build host with hyper-threading most likely shows
|
||||
eight processors, which is the value you would then assign to
|
||||
:term:`BB_NUMBER_THREADS`.
|
||||
|
||||
A possibly simpler solution is that some Linux distributions (e.g.
|
||||
Debian and Ubuntu) provide the ``ncpus`` command.
|
||||
|
||||
Parsing the Base Configuration Metadata
|
||||
=======================================
|
||||
|
||||
The first thing BitBake does is parse base configuration metadata. Base
|
||||
configuration metadata consists of your project's ``bblayers.conf`` file
|
||||
to determine what layers BitBake needs to recognize, all necessary
|
||||
``layer.conf`` files (one from each layer), and ``bitbake.conf``. The
|
||||
data itself is of various types:
|
||||
|
||||
- **Recipes:** Details about particular pieces of software.
|
||||
|
||||
- **Class Data:** An abstraction of common build information (e.g. how to
|
||||
build a Linux kernel).
|
||||
|
||||
- **Configuration Data:** Machine-specific settings, policy decisions,
|
||||
and so forth. Configuration data acts as the glue to bind everything
|
||||
together.
|
||||
|
||||
The ``layer.conf`` files are used to construct key variables such as
|
||||
:term:`BBPATH` and :term:`BBFILES`.
|
||||
:term:`BBPATH` is used to search for configuration and class files under the
|
||||
``conf`` and ``classes`` directories, respectively. :term:`BBFILES` is used
|
||||
to locate both recipe and recipe append files (``.bb`` and
|
||||
``.bbappend``). If there is no ``bblayers.conf`` file, it is assumed the
|
||||
user has set the :term:`BBPATH` and :term:`BBFILES` directly in the environment.
|
||||
|
||||
Next, the ``bitbake.conf`` file is located using the :term:`BBPATH` variable
|
||||
that was just constructed. The ``bitbake.conf`` file may also include
|
||||
other configuration files using the ``include`` or ``require``
|
||||
directives.
|
||||
|
||||
Prior to parsing configuration files, BitBake looks at certain
|
||||
variables, including:
|
||||
|
||||
- :term:`BB_ENV_PASSTHROUGH`
|
||||
- :term:`BB_ENV_PASSTHROUGH_ADDITIONS`
|
||||
- :term:`BB_PRESERVE_ENV`
|
||||
- :term:`BB_ORIGENV`
|
||||
- :term:`BITBAKE_UI`
|
||||
|
||||
The first four variables in this list relate to how BitBake treats shell
|
||||
environment variables during task execution. By default, BitBake cleans
|
||||
the environment variables and provides tight control over the shell
|
||||
execution environment. However, through the use of these first four
|
||||
variables, you can apply your control regarding the environment
|
||||
variables allowed to be used by BitBake in the shell during execution of
|
||||
tasks. See the
|
||||
":ref:`bitbake-user-manual/bitbake-user-manual-metadata:Passing Information Into the Build Task Environment`"
|
||||
section and the information about these variables in the variable
|
||||
glossary for more information on how they work and on how to use them.
|
||||
|
||||
The base configuration metadata is global and therefore affects all
|
||||
recipes and tasks that are executed.
|
||||
|
||||
BitBake first searches the current working directory for an optional
|
||||
``conf/bblayers.conf`` configuration file. This file is expected to
|
||||
contain a :term:`BBLAYERS` variable that is a
|
||||
space-delimited list of 'layer' directories. Recall that if BitBake
|
||||
cannot find a ``bblayers.conf`` file, then it is assumed the user has
|
||||
set the :term:`BBPATH` and :term:`BBFILES` variables directly in the
|
||||
environment.
|
||||
|
||||
For each directory (layer) in this list, a ``conf/layer.conf`` file is
|
||||
located and parsed with the :term:`LAYERDIR` variable
|
||||
being set to the directory where the layer was found. The idea is these
|
||||
files automatically set up :term:`BBPATH` and other
|
||||
variables correctly for a given build directory.
|
||||
|
||||
BitBake then expects to find the ``conf/bitbake.conf`` file somewhere in
|
||||
the user-specified :term:`BBPATH`. That configuration file generally has
|
||||
include directives to pull in any other metadata such as files specific
|
||||
to the architecture, the machine, the local environment, and so forth.
|
||||
|
||||
Only variable definitions and include directives are allowed in BitBake
|
||||
``.conf`` files. Some variables directly influence BitBake's behavior.
|
||||
These variables might have been set from the environment depending on
|
||||
the environment variables previously mentioned or set in the
|
||||
configuration files. The ":ref:`bitbake-user-manual/bitbake-user-manual-ref-variables:Variables Glossary`"
|
||||
chapter presents a full list of
|
||||
variables.
|
||||
|
||||
After parsing configuration files, BitBake uses its rudimentary
|
||||
inheritance mechanism, which is through class files, to inherit some
|
||||
standard classes. BitBake parses a class when the inherit directive
|
||||
responsible for getting that class is encountered.
|
||||
|
||||
The ``base.bbclass`` file is always included. Other classes that are
|
||||
specified in the configuration using the
|
||||
:term:`INHERIT` variable are also included. BitBake
|
||||
searches for class files in a ``classes`` subdirectory under the paths
|
||||
in :term:`BBPATH` in the same way as configuration files.
|
||||
|
||||
A good way to get an idea of the configuration files and the class files
|
||||
used in your execution environment is to run the following BitBake
|
||||
command::
|
||||
|
||||
$ bitbake -e > mybb.log
|
||||
|
||||
Examining the top of the ``mybb.log``
|
||||
shows you the many configuration files and class files used in your
|
||||
execution environment.
|
||||
|
||||
.. note::
|
||||
|
||||
You need to be aware of how BitBake parses curly braces. If a recipe
|
||||
uses a closing curly brace within the function and the character has
|
||||
no leading spaces, BitBake produces a parsing error. If you use a
|
||||
pair of curly braces in a shell function, the closing curly brace
|
||||
must not be located at the start of the line without leading spaces.
|
||||
|
||||
Here is an example that causes BitBake to produce a parsing error::
|
||||
|
||||
fakeroot create_shar() {
|
||||
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
|
||||
usage()
|
||||
{
|
||||
echo "test"
|
||||
###### The following "}" at the start of the line causes a parsing error ######
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
Writing the recipe this way avoids the error:
|
||||
fakeroot create_shar() {
|
||||
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
|
||||
usage()
|
||||
{
|
||||
echo "test"
|
||||
###### The following "}" with a leading space at the start of the line avoids the error ######
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
Locating and Parsing Recipes
|
||||
============================
|
||||
|
||||
During the configuration phase, BitBake will have set
|
||||
:term:`BBFILES`. BitBake now uses it to construct a
|
||||
list of recipes to parse, along with any append files (``.bbappend``) to
|
||||
apply. :term:`BBFILES` is a space-separated list of available files and
|
||||
supports wildcards. An example would be::
|
||||
|
||||
BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"
|
||||
|
||||
BitBake parses each
|
||||
recipe and append file located with :term:`BBFILES` and stores the values of
|
||||
various variables into the datastore.
|
||||
|
||||
.. note::
|
||||
|
||||
Append files are applied in the order they are encountered in BBFILES.
|
||||
|
||||
For each file, a fresh copy of the base configuration is made, then the
|
||||
recipe is parsed line by line. Any inherit statements cause BitBake to
|
||||
find and then parse class files (``.bbclass``) using
|
||||
:term:`BBPATH` as the search path. Finally, BitBake
|
||||
parses in order any append files found in :term:`BBFILES`.
|
||||
|
||||
One common convention is to use the recipe filename to define pieces of
|
||||
metadata. For example, in ``bitbake.conf`` the recipe name and version
|
||||
are used to set the variables :term:`PN` and
|
||||
:term:`PV`::
|
||||
|
||||
PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
|
||||
PV = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
|
||||
|
||||
In this example, a recipe called "something_1.2.3.bb" would set
|
||||
:term:`PN` to "something" and :term:`PV` to "1.2.3".
|
||||
|
||||
By the time parsing is complete for a recipe, BitBake has a list of
|
||||
tasks that the recipe defines and a set of data consisting of keys and
|
||||
values as well as dependency information about the tasks.
|
||||
|
||||
BitBake does not need all of this information. It only needs a small
|
||||
subset of the information to make decisions about the recipe.
|
||||
Consequently, BitBake caches the values in which it is interested and
|
||||
does not store the rest of the information. Experience has shown it is
|
||||
faster to re-parse the metadata than to try and write it out to the disk
|
||||
and then reload it.
|
||||
|
||||
Where possible, subsequent BitBake commands reuse this cache of recipe
|
||||
information. The validity of this cache is determined by first computing
|
||||
a checksum of the base configuration data (see
|
||||
:term:`BB_HASHCONFIG_IGNORE_VARS`) and
|
||||
then checking if the checksum matches. If that checksum matches what is
|
||||
in the cache and the recipe and class files have not changed, BitBake is
|
||||
able to use the cache. BitBake then reloads the cached information about
|
||||
the recipe instead of reparsing it from scratch.
|
||||
|
||||
Recipe file collections exist to allow the user to have multiple
|
||||
repositories of ``.bb`` files that contain the same exact package. For
|
||||
example, one could easily use them to make one's own local copy of an
|
||||
upstream repository, but with custom modifications that one does not
|
||||
want upstream. Here is an example::
|
||||
|
||||
BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
|
||||
BBFILE_COLLECTIONS = "upstream local"
|
||||
BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
|
||||
BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
|
||||
BBFILE_PRIORITY_upstream = "5"
|
||||
BBFILE_PRIORITY_local = "10"
|
||||
|
||||
.. note::
|
||||
|
||||
The layers mechanism is now the preferred method of collecting code.
|
||||
While the collections code remains, its main use is to set layer
|
||||
priorities and to deal with overlap (conflicts) between layers.
|
||||
|
||||
.. _bb-bitbake-providers:
|
||||
|
||||
Providers
|
||||
=========
|
||||
|
||||
Assuming BitBake has been instructed to execute a target and that all
|
||||
the recipe files have been parsed, BitBake starts to figure out how to
|
||||
build the target. BitBake looks through the :term:`PROVIDES` list for each
|
||||
of the recipes. A :term:`PROVIDES` list is the list of names by which the
|
||||
recipe can be known. Each recipe's :term:`PROVIDES` list is created
|
||||
implicitly through the recipe's :term:`PN` variable and
|
||||
explicitly through the recipe's :term:`PROVIDES`
|
||||
variable, which is optional.
|
||||
|
||||
When a recipe uses :term:`PROVIDES`, that recipe's functionality can be
|
||||
found under an alternative name or names other than the implicit :term:`PN`
|
||||
name. As an example, suppose a recipe named ``keyboard_1.0.bb``
|
||||
contained the following::
|
||||
|
||||
PROVIDES += "fullkeyboard"
|
||||
|
||||
The :term:`PROVIDES`
|
||||
list for this recipe becomes "keyboard", which is implicit, and
|
||||
"fullkeyboard", which is explicit. Consequently, the functionality found
|
||||
in ``keyboard_1.0.bb`` can be found under two different names.
|
||||
|
||||
.. _bb-bitbake-preferences:
|
||||
|
||||
Preferences
|
||||
===========
|
||||
|
||||
The :term:`PROVIDES` list is only part of the solution for figuring out a
|
||||
target's recipes. Because targets might have multiple providers, BitBake
|
||||
needs to prioritize providers by determining provider preferences.
|
||||
|
||||
A common example in which a target has multiple providers is
|
||||
"virtual/kernel", which is on the :term:`PROVIDES` list for each kernel
|
||||
recipe. Each machine often selects the best kernel provider by using a
|
||||
line similar to the following in the machine configuration file::
|
||||
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
|
||||
|
||||
The default :term:`PREFERRED_PROVIDER` is the provider
|
||||
with the same name as the target. BitBake iterates through each target
|
||||
it needs to build and resolves them and their dependencies using this
|
||||
process.
|
||||
|
||||
Understanding how providers are chosen is made complicated by the fact
|
||||
that multiple versions might exist for a given provider. BitBake
|
||||
defaults to the highest version of a provider. Version comparisons are
|
||||
made using the same method as Debian. You can use the
|
||||
:term:`PREFERRED_VERSION` variable to
|
||||
specify a particular version. You can influence the order by using the
|
||||
:term:`DEFAULT_PREFERENCE` variable.
|
||||
|
||||
By default, files have a preference of "0". Setting
|
||||
:term:`DEFAULT_PREFERENCE` to "-1" makes the recipe unlikely to be used
|
||||
unless it is explicitly referenced. Setting :term:`DEFAULT_PREFERENCE` to
|
||||
"1" makes it likely the recipe is used. :term:`PREFERRED_VERSION` overrides
|
||||
any :term:`DEFAULT_PREFERENCE` setting. :term:`DEFAULT_PREFERENCE` is often used
|
||||
to mark newer and more experimental recipe versions until they have
|
||||
undergone sufficient testing to be considered stable.
|
||||
|
||||
When there are multiple "versions" of a given recipe, BitBake defaults
|
||||
to selecting the most recent version, unless otherwise specified. If the
|
||||
recipe in question has a
|
||||
:term:`DEFAULT_PREFERENCE` set lower than
|
||||
the other recipes (default is 0), then it will not be selected. This
|
||||
allows the person or persons maintaining the repository of recipe files
|
||||
to specify their preference for the default selected version.
|
||||
Additionally, the user can specify their preferred version.
|
||||
|
||||
If the first recipe is named ``a_1.1.bb``, then the
|
||||
:term:`PN` variable will be set to "a", and the
|
||||
:term:`PV` variable will be set to 1.1.
|
||||
|
||||
Thus, if a recipe named ``a_1.2.bb`` exists, BitBake will choose 1.2 by
|
||||
default. However, if you define the following variable in a ``.conf``
|
||||
file that BitBake parses, you can change that preference::
|
||||
|
||||
PREFERRED_VERSION_a = "1.1"
|
||||
|
||||
.. note::
|
||||
|
||||
It is common for a recipe to provide two versions -- a stable,
|
||||
numbered (and preferred) version, and a version that is automatically
|
||||
checked out from a source code repository that is considered more
|
||||
"bleeding edge" but can be selected only explicitly.
|
||||
|
||||
For example, in the OpenEmbedded codebase, there is a standard,
|
||||
versioned recipe file for BusyBox, ``busybox_1.22.1.bb``, but there
|
||||
is also a Git-based version, ``busybox_git.bb``, which explicitly
|
||||
contains the line ::
|
||||
|
||||
DEFAULT_PREFERENCE = "-1"
|
||||
|
||||
to ensure that the
|
||||
numbered, stable version is always preferred unless the developer
|
||||
selects otherwise.
|
||||
|
||||
.. _bb-bitbake-dependencies:
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
Each target BitBake builds consists of multiple tasks such as ``fetch``,
|
||||
``unpack``, ``patch``, ``configure``, and ``compile``. For best
|
||||
performance on multi-core systems, BitBake considers each task as an
|
||||
independent entity with its own set of dependencies.
|
||||
|
||||
Dependencies are defined through several variables. You can find
|
||||
information about variables BitBake uses in the
|
||||
:doc:`bitbake-user-manual-ref-variables` near the end of this manual. At a
|
||||
basic level, it is sufficient to know that BitBake uses the
|
||||
:term:`DEPENDS` and
|
||||
:term:`RDEPENDS` variables when calculating
|
||||
dependencies.
|
||||
|
||||
For more information on how BitBake handles dependencies, see the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:Dependencies`
|
||||
section.
|
||||
|
||||
.. _ref-bitbake-tasklist:
|
||||
|
||||
The Task List
|
||||
=============
|
||||
|
||||
Based on the generated list of providers and the dependency information,
|
||||
BitBake can now calculate exactly what tasks it needs to run and in what
|
||||
order it needs to run them. The
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-execution:executing tasks`
|
||||
section has more information on how BitBake chooses which task to
|
||||
execute next.
|
||||
|
||||
The build now starts with BitBake forking off threads up to the limit
|
||||
set in the :term:`BB_NUMBER_THREADS`
|
||||
variable. BitBake continues to fork threads as long as there are tasks
|
||||
ready to run, those tasks have all their dependencies met, and the
|
||||
thread threshold has not been exceeded.
|
||||
|
||||
It is worth noting that you can greatly speed up the build time by
|
||||
properly setting the :term:`BB_NUMBER_THREADS` variable.
|
||||
|
||||
As each task completes, a timestamp is written to the directory
|
||||
specified by the :term:`STAMP` variable. On subsequent
|
||||
runs, BitBake looks in the build directory within ``tmp/stamps`` and
|
||||
does not rerun tasks that are already completed unless a timestamp is
|
||||
found to be invalid. Currently, invalid timestamps are only considered
|
||||
on a per recipe file basis. So, for example, if the configure stamp has
|
||||
a timestamp greater than the compile timestamp for a given target, then
|
||||
the compile task would rerun. Running the compile task again, however,
|
||||
has no effect on other providers that depend on that target.
|
||||
|
||||
The exact format of the stamps is partly configurable. In modern
|
||||
versions of BitBake, a hash is appended to the stamp so that if the
|
||||
configuration changes, the stamp becomes invalid and the task is
|
||||
automatically rerun. This hash, or signature used, is governed by the
|
||||
signature policy that is configured (see the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-execution:checksums (signatures)`
|
||||
section for information). It is also
|
||||
possible to append extra metadata to the stamp using the
|
||||
``[stamp-extra-info]`` task flag. For example, OpenEmbedded uses this
|
||||
flag to make some tasks machine-specific.
|
||||
|
||||
.. note::
|
||||
|
||||
Some tasks are marked as "nostamp" tasks. No timestamp file is
|
||||
created when these tasks are run. Consequently, "nostamp" tasks are
|
||||
always rerun.
|
||||
|
||||
For more information on tasks, see the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:tasks` section.
|
||||
|
||||
Executing Tasks
|
||||
===============
|
||||
|
||||
Tasks can be either a shell task or a Python task. For shell tasks,
|
||||
BitBake writes a shell script to
|
||||
``${``\ :term:`T`\ ``}/run.do_taskname.pid`` and then
|
||||
executes the script. The generated shell script contains all the
|
||||
exported variables, and the shell functions with all variables expanded.
|
||||
Output from the shell script goes to the file
|
||||
``${``\ :term:`T`\ ``}/log.do_taskname.pid``. Looking at the expanded shell functions in
|
||||
the run file and the output in the log files is a useful debugging
|
||||
technique.
|
||||
|
||||
For Python tasks, BitBake executes the task internally and logs
|
||||
information to the controlling terminal. Future versions of BitBake will
|
||||
write the functions to files similar to the way shell tasks are handled.
|
||||
Logging will be handled in a way similar to shell tasks as well.
|
||||
|
||||
The order in which BitBake runs the tasks is controlled by its task
|
||||
scheduler. It is possible to configure the scheduler and define custom
|
||||
implementations for specific use cases. For more information, see these
|
||||
variables that control the behavior:
|
||||
|
||||
- :term:`BB_SCHEDULER`
|
||||
|
||||
- :term:`BB_SCHEDULERS`
|
||||
|
||||
It is possible to have functions run before and after a task's main
|
||||
function. This is done using the ``[prefuncs]`` and ``[postfuncs]``
|
||||
flags of the task that lists the functions to run.
|
||||
|
||||
.. _checksums:
|
||||
|
||||
Checksums (Signatures)
|
||||
======================
|
||||
|
||||
A checksum is a unique signature of a task's inputs. The signature of a
|
||||
task can be used to determine if a task needs to be run. Because it is a
|
||||
change in a task's inputs that triggers running the task, BitBake needs
|
||||
to detect all the inputs to a given task. For shell tasks, this turns
|
||||
out to be fairly easy because BitBake generates a "run" shell script for
|
||||
each task and it is possible to create a checksum that gives you a good
|
||||
idea of when the task's data changes.
|
||||
|
||||
To complicate the problem, some things should not be included in the
|
||||
checksum. First, there is the actual specific build path of a given task
|
||||
- the working directory. It does not matter if the working directory
|
||||
changes because it should not affect the output for target packages. The
|
||||
simplistic approach for excluding the working directory is to set it to
|
||||
some fixed value and create the checksum for the "run" script. BitBake
|
||||
goes one step better and uses the
|
||||
:term:`BB_BASEHASH_IGNORE_VARS` variable
|
||||
to define a list of variables that should never be included when
|
||||
generating the signatures.
|
||||
|
||||
Another problem results from the "run" scripts containing functions that
|
||||
might or might not get called. The incremental build solution contains
|
||||
code that figures out dependencies between shell functions. This code is
|
||||
used to prune the "run" scripts down to the minimum set, thereby
|
||||
alleviating this problem and making the "run" scripts much more readable
|
||||
as a bonus.
|
||||
|
||||
So far we have solutions for shell scripts. What about Python tasks? The
|
||||
same approach applies even though these tasks are more difficult. The
|
||||
process needs to figure out what variables a Python function accesses
|
||||
and what functions it calls. Again, the incremental build solution
|
||||
contains code that first figures out the variable and function
|
||||
dependencies, and then creates a checksum for the data used as the input
|
||||
to the task.
|
||||
|
||||
Like the working directory case, situations exist where dependencies
|
||||
should be ignored. For these cases, you can instruct the build process
|
||||
to ignore a dependency by using a line like the following::
|
||||
|
||||
PACKAGE_ARCHS[vardepsexclude] = "MACHINE"
|
||||
|
||||
This example ensures that the
|
||||
``PACKAGE_ARCHS`` variable does not depend on the value of ``MACHINE``,
|
||||
even if it does reference it.
|
||||
|
||||
Equally, there are cases where we need to add dependencies BitBake is
|
||||
not able to find. You can accomplish this by using a line like the
|
||||
following::
|
||||
|
||||
PACKAGE_ARCHS[vardeps] = "MACHINE"
|
||||
|
||||
This example explicitly
|
||||
adds the ``MACHINE`` variable as a dependency for ``PACKAGE_ARCHS``.
|
||||
|
||||
Consider a case with in-line Python, for example, where BitBake is not
|
||||
able to figure out dependencies. When running in debug mode (i.e. using
|
||||
``-DDD``), BitBake produces output when it discovers something for which
|
||||
it cannot figure out dependencies.
|
||||
|
||||
Thus far, this section has limited discussion to the direct inputs into
|
||||
a task. Information based on direct inputs is referred to as the
|
||||
"basehash" in the code. However, there is still the question of a task's
|
||||
indirect inputs --- the things that were already built and present in the
|
||||
build directory. The checksum (or signature) for a particular task needs
|
||||
to add the hashes of all the tasks on which the particular task depends.
|
||||
Choosing which dependencies to add is a policy decision. However, the
|
||||
effect is to generate a master checksum that combines the basehash and
|
||||
the hashes of the task's dependencies.
|
||||
|
||||
At the code level, there are a variety of ways both the basehash and the
|
||||
dependent task hashes can be influenced. Within the BitBake
|
||||
configuration file, we can give BitBake some extra information to help
|
||||
it construct the basehash. The following statement effectively results
|
||||
in a list of global variable dependency excludes --- variables never
|
||||
included in any checksum. This example uses variables from OpenEmbedded
|
||||
to help illustrate the concept::
|
||||
|
||||
BB_BASEHASH_IGNORE_VARS ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
|
||||
SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL \
|
||||
USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
|
||||
PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
|
||||
CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"
|
||||
|
||||
The previous example excludes the work directory, which is part of
|
||||
``TMPDIR``.
|
||||
|
||||
The rules for deciding which hashes of dependent tasks to include
|
||||
through dependency chains are more complex and are generally
|
||||
accomplished with a Python function. The code in
|
||||
``meta/lib/oe/sstatesig.py`` shows two examples of this and also
|
||||
illustrates how you can insert your own policy into the system if so
|
||||
desired. This file defines the basic signature generator
|
||||
OpenEmbedded-Core uses: "OEBasicHash". By default, there
|
||||
is a dummy "noop" signature handler enabled in BitBake. This means that
|
||||
behavior is unchanged from previous versions. ``OE-Core`` uses the
|
||||
"OEBasicHash" signature handler by default through this setting in the
|
||||
``bitbake.conf`` file::
|
||||
|
||||
BB_SIGNATURE_HANDLER ?= "OEBasicHash"
|
||||
|
||||
The main feature of the "OEBasicHash" :term:`BB_SIGNATURE_HANDLER` is that
|
||||
it adds the task hash to the stamp files. Thanks to this, any metadata
|
||||
change will change the task hash, automatically causing the task to be run
|
||||
again. This removes the need to bump :term:`PR` values, and changes to
|
||||
metadata automatically ripple across the build.
|
||||
|
||||
It is also worth noting that the end result of signature
|
||||
generators is to make some dependency and hash information available to
|
||||
the build. This information includes:
|
||||
|
||||
- ``BB_BASEHASH_task-``\ *taskname*: The base hashes for each task in the
|
||||
recipe.
|
||||
|
||||
- ``BB_BASEHASH_``\ *filename:taskname*: The base hashes for each
|
||||
dependent task.
|
||||
|
||||
- :term:`BB_TASKHASH`: The hash of the currently running task.
|
||||
|
||||
It is worth noting that BitBake's "-S" option lets you debug BitBake's
|
||||
processing of signatures. The options passed to -S allow different
|
||||
debugging modes to be used, either using BitBake's own debug functions
|
||||
or possibly those defined in the metadata/signature handler itself. The
|
||||
simplest parameter to pass is "none", which causes a set of signature
|
||||
information to be written out into ``STAMPS_DIR`` corresponding to the
|
||||
targets specified. The other currently available parameter is
|
||||
"printdiff", which causes BitBake to try to establish the most recent
|
||||
signature match it can (e.g. in the sstate cache) and then run
|
||||
compare the matched signatures to determine the stamps and delta
|
||||
where these two stamp trees diverge. This can be used to determine why
|
||||
tasks need to be re-run in situations where that is not expected.
|
||||
|
||||
.. note::
|
||||
|
||||
It is likely that future versions of BitBake will provide other
|
||||
signature handlers triggered through additional "-S" parameters.
|
||||
|
||||
You can find more information on checksum metadata in the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
|
||||
section.
|
||||
|
||||
Setscene
|
||||
========
|
||||
|
||||
The setscene process enables BitBake to handle "pre-built" artifacts.
|
||||
The ability to handle and reuse these artifacts allows BitBake the
|
||||
luxury of not having to build something from scratch every time.
|
||||
Instead, BitBake can use, when possible, existing build artifacts.
|
||||
|
||||
BitBake needs to have reliable data indicating whether or not an
|
||||
artifact is compatible. Signatures, described in the previous section,
|
||||
provide an ideal way of representing whether an artifact is compatible.
|
||||
If a signature is the same, an object can be reused.
|
||||
|
||||
If an object can be reused, the problem then becomes how to replace a
|
||||
given task or set of tasks with the pre-built artifact. BitBake solves
|
||||
the problem with the "setscene" process.
|
||||
|
||||
When BitBake is asked to build a given target, before building anything,
|
||||
it first asks whether cached information is available for any of the
|
||||
targets it's building, or any of the intermediate targets. If cached
|
||||
information is available, BitBake uses this information instead of
|
||||
running the main tasks.
|
||||
|
||||
BitBake first calls the function defined by the
|
||||
:term:`BB_HASHCHECK_FUNCTION` variable
|
||||
with a list of tasks and corresponding hashes it wants to build. This
|
||||
function is designed to be fast and returns a list of the tasks for
|
||||
which it believes in can obtain artifacts.
|
||||
|
||||
Next, for each of the tasks that were returned as possibilities, BitBake
|
||||
executes a setscene version of the task that the possible artifact
|
||||
covers. Setscene versions of a task have the string "_setscene" appended
|
||||
to the task name. So, for example, the task with the name ``xxx`` has a
|
||||
setscene task named ``xxx_setscene``. The setscene version of the task
|
||||
executes and provides the necessary artifacts returning either success
|
||||
or failure.
|
||||
|
||||
As previously mentioned, an artifact can cover more than one task. For
|
||||
example, it is pointless to obtain a compiler if you already have the
|
||||
compiled binary. To handle this, BitBake calls the
|
||||
:term:`BB_SETSCENE_DEPVALID` function for
|
||||
each successful setscene task to know whether or not it needs to obtain
|
||||
the dependencies of that task.
|
||||
|
||||
You can find more information on setscene metadata in the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-metadata:task checksums and setscene`
|
||||
section.
|
||||
|
||||
Logging
|
||||
=======
|
||||
|
||||
In addition to the standard command line option to control how verbose
|
||||
builds are when execute, bitbake also supports user defined
|
||||
configuration of the `Python
|
||||
logging <https://docs.python.org/3/library/logging.html>`__ facilities
|
||||
through the :term:`BB_LOGCONFIG` variable. This
|
||||
variable defines a JSON or YAML `logging
|
||||
configuration <https://docs.python.org/3/library/logging.config.html>`__
|
||||
that will be intelligently merged into the default configuration. The
|
||||
logging configuration is merged using the following rules:
|
||||
|
||||
- The user defined configuration will completely replace the default
|
||||
configuration if top level key ``bitbake_merge`` is set to the value
|
||||
``False``. In this case, all other rules are ignored.
|
||||
|
||||
- The user configuration must have a top level ``version`` which must
|
||||
match the value of the default configuration.
|
||||
|
||||
- Any keys defined in the ``handlers``, ``formatters``, or ``filters``,
|
||||
will be merged into the same section in the default configuration,
|
||||
with the user specified keys taking replacing a default one if there
|
||||
is a conflict. In practice, this means that if both the default
|
||||
configuration and user configuration specify a handler named
|
||||
``myhandler``, the user defined one will replace the default. To
|
||||
prevent the user from inadvertently replacing a default handler,
|
||||
formatter, or filter, all of the default ones are named with a prefix
|
||||
of "``BitBake.``"
|
||||
|
||||
- If a logger is defined by the user with the key ``bitbake_merge`` set
|
||||
to ``False``, that logger will be completely replaced by user
|
||||
configuration. In this case, no other rules will apply to that
|
||||
logger.
|
||||
|
||||
- All user defined ``filter`` and ``handlers`` properties for a given
|
||||
logger will be merged with corresponding properties from the default
|
||||
logger. For example, if the user configuration adds a filter called
|
||||
``myFilter`` to the ``BitBake.SigGen``, and the default configuration
|
||||
adds a filter called ``BitBake.defaultFilter``, both filters will be
|
||||
applied to the logger
|
||||
|
||||
As a first example, you can create a ``hashequiv.json`` user logging
|
||||
configuration file to log all Hash Equivalence related messages of ``VERBOSE``
|
||||
or higher priority to a file called ``hashequiv.log``::
|
||||
|
||||
{
|
||||
"version": 1,
|
||||
"handlers": {
|
||||
"autobuilderlog": {
|
||||
"class": "logging.FileHandler",
|
||||
"formatter": "logfileFormatter",
|
||||
"level": "DEBUG",
|
||||
"filename": "hashequiv.log",
|
||||
"mode": "w"
|
||||
}
|
||||
},
|
||||
"formatters": {
|
||||
"logfileFormatter": {
|
||||
"format": "%(name)s: %(levelname)s: %(message)s"
|
||||
}
|
||||
},
|
||||
"loggers": {
|
||||
"BitBake.SigGen.HashEquiv": {
|
||||
"level": "VERBOSE",
|
||||
"handlers": ["autobuilderlog"]
|
||||
},
|
||||
"BitBake.RunQueue.HashEquiv": {
|
||||
"level": "VERBOSE",
|
||||
"handlers": ["autobuilderlog"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Then set the :term:`BB_LOGCONFIG` variable in ``conf/local.conf``::
|
||||
|
||||
BB_LOGCONFIG = "hashequiv.json"
|
||||
|
||||
Another example is this ``warn.json`` file to log all ``WARNING`` and
|
||||
higher priority messages to a ``warn.log`` file::
|
||||
|
||||
{
|
||||
"version": 1,
|
||||
"formatters": {
|
||||
"warnlogFormatter": {
|
||||
"()": "bb.msg.BBLogFormatter",
|
||||
"format": "%(levelname)s: %(message)s"
|
||||
}
|
||||
},
|
||||
|
||||
"handlers": {
|
||||
"warnlog": {
|
||||
"class": "logging.FileHandler",
|
||||
"formatter": "warnlogFormatter",
|
||||
"level": "WARNING",
|
||||
"filename": "warn.log"
|
||||
}
|
||||
},
|
||||
|
||||
"loggers": {
|
||||
"BitBake": {
|
||||
"handlers": ["warnlog"]
|
||||
}
|
||||
},
|
||||
|
||||
"@disable_existing_loggers": false
|
||||
}
|
||||
|
||||
Note that BitBake's helper classes for structured logging are implemented in
|
||||
``lib/bb/msg.py``.
|
||||
@@ -0,0 +1,932 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<chapter id="bitbake-user-manual-execution">
|
||||
<title>Execution</title>
|
||||
|
||||
<para>
|
||||
The primary purpose for running BitBake is to produce some kind
|
||||
of output such as a single installable package, a kernel, a software
|
||||
development kit, or even a full, board-specific bootable Linux image,
|
||||
complete with bootloader, kernel, and root filesystem.
|
||||
Of course, you can execute the <filename>bitbake</filename>
|
||||
command with options that cause it to execute single tasks,
|
||||
compile single recipe files, capture or clear data, or simply
|
||||
return information about the execution environment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This chapter describes BitBake's execution process from start
|
||||
to finish when you use it to create an image.
|
||||
The execution process is launched using the following command
|
||||
form:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake <replaceable>target</replaceable>
|
||||
</literallayout>
|
||||
For information on the BitBake command and its options,
|
||||
see
|
||||
"<link linkend='bitbake-user-manual-command'>The BitBake Command</link>"
|
||||
section.
|
||||
<note>
|
||||
<para>
|
||||
Prior to executing BitBake, you should take advantage of available
|
||||
parallel thread execution on your build host by setting the
|
||||
<link linkend='var-bb-BB_NUMBER_THREADS'><filename>BB_NUMBER_THREADS</filename></link>
|
||||
variable in your project's <filename>local.conf</filename>
|
||||
configuration file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A common method to determine this value for your build host is to run
|
||||
the following:
|
||||
<literallayout class='monospaced'>
|
||||
$ grep processor /proc/cpuinfo
|
||||
</literallayout>
|
||||
This command returns the number of processors, which takes into
|
||||
account hyper-threading.
|
||||
Thus, a quad-core build host with hyper-threading most likely
|
||||
shows eight processors, which is the value you would then assign to
|
||||
<filename>BB_NUMBER_THREADS</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A possibly simpler solution is that some Linux distributions
|
||||
(e.g. Debian and Ubuntu) provide the <filename>ncpus</filename> command.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<section id='parsing-the-base-configuration-metadata'>
|
||||
<title>Parsing the Base Configuration Metadata</title>
|
||||
|
||||
<para>
|
||||
The first thing BitBake does is parse base configuration
|
||||
metadata.
|
||||
Base configuration metadata consists of your project's
|
||||
<filename>bblayers.conf</filename> file to determine what
|
||||
layers BitBake needs to recognize, all necessary
|
||||
<filename>layer.conf</filename> files (one from each layer),
|
||||
and <filename>bitbake.conf</filename>.
|
||||
The data itself is of various types:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Recipes:</emphasis>
|
||||
Details about particular pieces of software.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Class Data:</emphasis>
|
||||
An abstraction of common build information
|
||||
(e.g. how to build a Linux kernel).
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Configuration Data:</emphasis>
|
||||
Machine-specific settings, policy decisions,
|
||||
and so forth.
|
||||
Configuration data acts as the glue to bind everything
|
||||
together.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>layer.conf</filename> files are used to
|
||||
construct key variables such as
|
||||
<link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
|
||||
and
|
||||
<link linkend='var-bb-BBFILES'><filename>BBFILES</filename></link>.
|
||||
<filename>BBPATH</filename> is used to search for
|
||||
configuration and class files under the
|
||||
<filename>conf</filename> and <filename>classes</filename>
|
||||
directories, respectively.
|
||||
<filename>BBFILES</filename> is used to locate both recipe
|
||||
and recipe append files
|
||||
(<filename>.bb</filename> and <filename>.bbappend</filename>).
|
||||
If there is no <filename>bblayers.conf</filename> file,
|
||||
it is assumed the user has set the <filename>BBPATH</filename>
|
||||
and <filename>BBFILES</filename> directly in the environment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, the <filename>bitbake.conf</filename> file is located
|
||||
using the <filename>BBPATH</filename> variable that was
|
||||
just constructed.
|
||||
The <filename>bitbake.conf</filename> file may also include other
|
||||
configuration files using the
|
||||
<filename>include</filename> or
|
||||
<filename>require</filename> directives.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Prior to parsing configuration files, Bitbake looks
|
||||
at certain variables, including:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_ORIGENV'><filename>BB_ORIGENV</filename></link>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BITBAKE_UI'><filename>BITBAKE_UI</filename></link>
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
The first four variables in this list relate to how BitBake treats shell
|
||||
environment variables during task execution.
|
||||
By default, BitBake cleans the environment variables and provides tight
|
||||
control over the shell execution environment.
|
||||
However, through the use of these first four variables, you can
|
||||
apply your control regarding the
|
||||
environment variables allowed to be used by BitBake in the shell
|
||||
during execution of tasks.
|
||||
See the
|
||||
"<link linkend='passing-information-into-the-build-task-environment'>Passing Information Into the Build Task Environment</link>"
|
||||
section and the information about these variables in the
|
||||
variable glossary for more information on how they work and
|
||||
on how to use them.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The base configuration metadata is global
|
||||
and therefore affects all recipes and tasks that are executed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake first searches the current working directory for an
|
||||
optional <filename>conf/bblayers.conf</filename> configuration file.
|
||||
This file is expected to contain a
|
||||
<link linkend='var-bb-BBLAYERS'><filename>BBLAYERS</filename></link>
|
||||
variable that is a space-delimited list of 'layer' directories.
|
||||
Recall that if BitBake cannot find a <filename>bblayers.conf</filename>
|
||||
file, then it is assumed the user has set the <filename>BBPATH</filename>
|
||||
and <filename>BBFILES</filename> variables directly in the environment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For each directory (layer) in this list, a <filename>conf/layer.conf</filename>
|
||||
file is located and parsed with the
|
||||
<link linkend='var-bb-LAYERDIR'><filename>LAYERDIR</filename></link>
|
||||
variable being set to the directory where the layer was found.
|
||||
The idea is these files automatically set up
|
||||
<link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
|
||||
and other variables correctly for a given build directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake then expects to find the <filename>conf/bitbake.conf</filename>
|
||||
file somewhere in the user-specified <filename>BBPATH</filename>.
|
||||
That configuration file generally has include directives to pull
|
||||
in any other metadata such as files specific to the architecture,
|
||||
the machine, the local environment, and so forth.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Only variable definitions and include directives are allowed
|
||||
in BitBake <filename>.conf</filename> files.
|
||||
Some variables directly influence BitBake's behavior.
|
||||
These variables might have been set from the environment
|
||||
depending on the environment variables previously
|
||||
mentioned or set in the configuration files.
|
||||
The
|
||||
"<link linkend='ref-bb-variables-glos'>Variables Glossary</link>"
|
||||
chapter presents a full list of variables.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After parsing configuration files, BitBake uses its rudimentary
|
||||
inheritance mechanism, which is through class files, to inherit
|
||||
some standard classes.
|
||||
BitBake parses a class when the inherit directive responsible
|
||||
for getting that class is encountered.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>base.bbclass</filename> file is always included.
|
||||
Other classes that are specified in the configuration using the
|
||||
<link linkend='var-bb-INHERIT'><filename>INHERIT</filename></link>
|
||||
variable are also included.
|
||||
BitBake searches for class files in a
|
||||
<filename>classes</filename> subdirectory under
|
||||
the paths in <filename>BBPATH</filename> in the same way as
|
||||
configuration files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A good way to get an idea of the configuration files and
|
||||
the class files used in your execution environment is to
|
||||
run the following BitBake command:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -e > mybb.log
|
||||
</literallayout>
|
||||
Examining the top of the <filename>mybb.log</filename>
|
||||
shows you the many configuration files and class files
|
||||
used in your execution environment.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
You need to be aware of how BitBake parses curly braces.
|
||||
If a recipe uses a closing curly brace within the function and
|
||||
the character has no leading spaces, BitBake produces a parsing
|
||||
error.
|
||||
If you use a pair of curly braces in a shell function, the
|
||||
closing curly brace must not be located at the start of the line
|
||||
without leading spaces.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is an example that causes BitBake to produce a parsing
|
||||
error:
|
||||
<literallayout class='monospaced'>
|
||||
fakeroot create_shar() {
|
||||
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
|
||||
usage()
|
||||
{
|
||||
echo "test"
|
||||
###### The following "}" at the start of the line causes a parsing error ######
|
||||
}
|
||||
EOF
|
||||
}
|
||||
</literallayout>
|
||||
Writing the recipe this way avoids the error:
|
||||
<literallayout class='monospaced'>
|
||||
fakeroot create_shar() {
|
||||
cat << "EOF" > ${SDK_DEPLOY}/${TOOLCHAIN_OUTPUTNAME}.sh
|
||||
usage()
|
||||
{
|
||||
echo "test"
|
||||
######The following "}" with a leading space at the start of the line avoids the error ######
|
||||
}
|
||||
EOF
|
||||
}
|
||||
</literallayout>
|
||||
</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id='locating-and-parsing-recipes'>
|
||||
<title>Locating and Parsing Recipes</title>
|
||||
|
||||
<para>
|
||||
During the configuration phase, BitBake will have set
|
||||
<link linkend='var-bb-BBFILES'><filename>BBFILES</filename></link>.
|
||||
BitBake now uses it to construct a list of recipes to parse,
|
||||
along with any append files (<filename>.bbappend</filename>)
|
||||
to apply.
|
||||
<filename>BBFILES</filename> is a space-separated list of
|
||||
available files and supports wildcards.
|
||||
An example would be:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILES = "/path/to/bbfiles/*.bb /path/to/appends/*.bbappend"
|
||||
</literallayout>
|
||||
BitBake parses each recipe and append file located
|
||||
with <filename>BBFILES</filename> and stores the values of
|
||||
various variables into the datastore.
|
||||
<note>
|
||||
Append files are applied in the order they are encountered in
|
||||
<filename>BBFILES</filename>.
|
||||
</note>
|
||||
For each file, a fresh copy of the base configuration is
|
||||
made, then the recipe is parsed line by line.
|
||||
Any inherit statements cause BitBake to find and
|
||||
then parse class files (<filename>.bbclass</filename>)
|
||||
using
|
||||
<link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
|
||||
as the search path.
|
||||
Finally, BitBake parses in order any append files found in
|
||||
<filename>BBFILES</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One common convention is to use the recipe filename to define
|
||||
pieces of metadata.
|
||||
For example, in <filename>bitbake.conf</filename> the recipe
|
||||
name and version are used to set the variables
|
||||
<link linkend='var-bb-PN'><filename>PN</filename></link> and
|
||||
<link linkend='var-bb-PV'><filename>PV</filename></link>:
|
||||
<literallayout class='monospaced'>
|
||||
PN = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
|
||||
PV = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[1] or '1.0'}"
|
||||
</literallayout>
|
||||
In this example, a recipe called "something_1.2.3.bb" would set
|
||||
<filename>PN</filename> to "something" and
|
||||
<filename>PV</filename> to "1.2.3".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By the time parsing is complete for a recipe, BitBake
|
||||
has a list of tasks that the recipe defines and a set of
|
||||
data consisting of keys and values as well as
|
||||
dependency information about the tasks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake does not need all of this information.
|
||||
It only needs a small subset of the information to make
|
||||
decisions about the recipe.
|
||||
Consequently, BitBake caches the values in which it is
|
||||
interested and does not store the rest of the information.
|
||||
Experience has shown it is faster to re-parse the metadata than to
|
||||
try and write it out to the disk and then reload it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Where possible, subsequent BitBake commands reuse this cache of
|
||||
recipe information.
|
||||
The validity of this cache is determined by first computing a
|
||||
checksum of the base configuration data (see
|
||||
<link linkend='var-bb-BB_HASHCONFIG_WHITELIST'><filename>BB_HASHCONFIG_WHITELIST</filename></link>)
|
||||
and then checking if the checksum matches.
|
||||
If that checksum matches what is in the cache and the recipe
|
||||
and class files have not changed, Bitbake is able to use
|
||||
the cache.
|
||||
BitBake then reloads the cached information about the recipe
|
||||
instead of reparsing it from scratch.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Recipe file collections exist to allow the user to
|
||||
have multiple repositories of
|
||||
<filename>.bb</filename> files that contain the same
|
||||
exact package.
|
||||
For example, one could easily use them to make one's
|
||||
own local copy of an upstream repository, but with
|
||||
custom modifications that one does not want upstream.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
|
||||
BBFILE_COLLECTIONS = "upstream local"
|
||||
BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
|
||||
BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
|
||||
BBFILE_PRIORITY_upstream = "5"
|
||||
BBFILE_PRIORITY_local = "10"
|
||||
</literallayout>
|
||||
<note>
|
||||
The layers mechanism is now the preferred method of collecting
|
||||
code.
|
||||
While the collections code remains, its main use is to set layer
|
||||
priorities and to deal with overlap (conflicts) between layers.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bb-bitbake-providers'>
|
||||
<title>Providers</title>
|
||||
|
||||
<para>
|
||||
Assuming BitBake has been instructed to execute a target
|
||||
and that all the recipe files have been parsed, BitBake
|
||||
starts to figure out how to build the target.
|
||||
BitBake looks through the <filename>PROVIDES</filename> list
|
||||
for each of the recipes.
|
||||
A <filename>PROVIDES</filename> list is the list of names by which
|
||||
the recipe can be known.
|
||||
Each recipe's <filename>PROVIDES</filename> list is created
|
||||
implicitly through the recipe's
|
||||
<link linkend='var-bb-PN'><filename>PN</filename></link> variable
|
||||
and explicitly through the recipe's
|
||||
<link linkend='var-bb-PROVIDES'><filename>PROVIDES</filename></link>
|
||||
variable, which is optional.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a recipe uses <filename>PROVIDES</filename>, that recipe's
|
||||
functionality can be found under an alternative name or names other
|
||||
than the implicit <filename>PN</filename> name.
|
||||
As an example, suppose a recipe named <filename>keyboard_1.0.bb</filename>
|
||||
contained the following:
|
||||
<literallayout class='monospaced'>
|
||||
PROVIDES += "fullkeyboard"
|
||||
</literallayout>
|
||||
The <filename>PROVIDES</filename> list for this recipe becomes
|
||||
"keyboard", which is implicit, and "fullkeyboard", which is explicit.
|
||||
Consequently, the functionality found in
|
||||
<filename>keyboard_1.0.bb</filename> can be found under two
|
||||
different names.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bb-bitbake-preferences'>
|
||||
<title>Preferences</title>
|
||||
|
||||
<para>
|
||||
The <filename>PROVIDES</filename> list is only part of the solution
|
||||
for figuring out a target's recipes.
|
||||
Because targets might have multiple providers, BitBake needs
|
||||
to prioritize providers by determining provider preferences.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A common example in which a target has multiple providers
|
||||
is "virtual/kernel", which is on the
|
||||
<filename>PROVIDES</filename> list for each kernel recipe.
|
||||
Each machine often selects the best kernel provider by using a
|
||||
line similar to the following in the machine configuration file:
|
||||
<literallayout class='monospaced'>
|
||||
PREFERRED_PROVIDER_virtual/kernel = "linux-yocto"
|
||||
</literallayout>
|
||||
The default
|
||||
<link linkend='var-bb-PREFERRED_PROVIDER'><filename>PREFERRED_PROVIDER</filename></link>
|
||||
is the provider with the same name as the target.
|
||||
Bitbake iterates through each target it needs to build and
|
||||
resolves them and their dependencies using this process.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Understanding how providers are chosen is made complicated by the fact
|
||||
that multiple versions might exist for a given provider.
|
||||
BitBake defaults to the highest version of a provider.
|
||||
Version comparisons are made using the same method as Debian.
|
||||
You can use the
|
||||
<link linkend='var-bb-PREFERRED_VERSION'><filename>PREFERRED_VERSION</filename></link>
|
||||
variable to specify a particular version.
|
||||
You can influence the order by using the
|
||||
<link linkend='var-bb-DEFAULT_PREFERENCE'><filename>DEFAULT_PREFERENCE</filename></link>
|
||||
variable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, files have a preference of "0".
|
||||
Setting <filename>DEFAULT_PREFERENCE</filename> to "-1" makes the
|
||||
recipe unlikely to be used unless it is explicitly referenced.
|
||||
Setting <filename>DEFAULT_PREFERENCE</filename> to "1" makes it
|
||||
likely the recipe is used.
|
||||
<filename>PREFERRED_VERSION</filename> overrides any
|
||||
<filename>DEFAULT_PREFERENCE</filename> setting.
|
||||
<filename>DEFAULT_PREFERENCE</filename> is often used to mark newer
|
||||
and more experimental recipe versions until they have undergone
|
||||
sufficient testing to be considered stable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When there are multiple “versions” of a given recipe,
|
||||
BitBake defaults to selecting the most recent
|
||||
version, unless otherwise specified.
|
||||
If the recipe in question has a
|
||||
<link linkend='var-bb-DEFAULT_PREFERENCE'><filename>DEFAULT_PREFERENCE</filename></link>
|
||||
set lower than the other recipes (default is 0), then
|
||||
it will not be selected.
|
||||
This allows the person or persons maintaining
|
||||
the repository of recipe files to specify
|
||||
their preference for the default selected version.
|
||||
Additionally, the user can specify their preferred version.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the first recipe is named <filename>a_1.1.bb</filename>, then the
|
||||
<link linkend='var-bb-PN'><filename>PN</filename></link> variable
|
||||
will be set to “a”, and the
|
||||
<link linkend='var-bb-PV'><filename>PV</filename></link>
|
||||
variable will be set to 1.1.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Thus, if a recipe named <filename>a_1.2.bb</filename> exists, BitBake
|
||||
will choose 1.2 by default.
|
||||
However, if you define the following variable in a
|
||||
<filename>.conf</filename> file that BitBake parses, you
|
||||
can change that preference:
|
||||
<literallayout class='monospaced'>
|
||||
PREFERRED_VERSION_a = "1.1"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
It is common for a recipe to provide two versions -- a stable,
|
||||
numbered (and preferred) version, and a version that is
|
||||
automatically checked out from a source code repository that
|
||||
is considered more "bleeding edge" but can be selected only
|
||||
explicitly.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For example, in the OpenEmbedded codebase, there is a standard,
|
||||
versioned recipe file for BusyBox,
|
||||
<filename>busybox_1.22.1.bb</filename>,
|
||||
but there is also a Git-based version,
|
||||
<filename>busybox_git.bb</filename>, which explicitly contains the line
|
||||
<literallayout class='monospaced'>
|
||||
DEFAULT_PREFERENCE = "-1"
|
||||
</literallayout>
|
||||
to ensure that the numbered, stable version is always preferred
|
||||
unless the developer selects otherwise.
|
||||
</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id='bb-bitbake-dependencies'>
|
||||
<title>Dependencies</title>
|
||||
|
||||
<para>
|
||||
Each target BitBake builds consists of multiple tasks such as
|
||||
<filename>fetch</filename>, <filename>unpack</filename>,
|
||||
<filename>patch</filename>, <filename>configure</filename>,
|
||||
and <filename>compile</filename>.
|
||||
For best performance on multi-core systems, BitBake considers each
|
||||
task as an independent
|
||||
entity with its own set of dependencies.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Dependencies are defined through several variables.
|
||||
You can find information about variables BitBake uses in
|
||||
the <link linkend='ref-bb-variables-glos'>Variables Glossary</link>
|
||||
near the end of this manual.
|
||||
At a basic level, it is sufficient to know that BitBake uses the
|
||||
<link linkend='var-bb-DEPENDS'><filename>DEPENDS</filename></link> and
|
||||
<link linkend='var-bb-RDEPENDS'><filename>RDEPENDS</filename></link> variables when
|
||||
calculating dependencies.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more information on how BitBake handles dependencies, see the
|
||||
"<link linkend='dependencies'>Dependencies</link>" section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='ref-bitbake-tasklist'>
|
||||
<title>The Task List</title>
|
||||
|
||||
<para>
|
||||
Based on the generated list of providers and the dependency information,
|
||||
BitBake can now calculate exactly what tasks it needs to run and in what
|
||||
order it needs to run them.
|
||||
The
|
||||
"<link linkend='executing-tasks'>Executing Tasks</link>" section has more
|
||||
information on how BitBake chooses which task to execute next.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The build now starts with BitBake forking off threads up to the limit set in the
|
||||
<link linkend='var-bb-BB_NUMBER_THREADS'><filename>BB_NUMBER_THREADS</filename></link>
|
||||
variable.
|
||||
BitBake continues to fork threads as long as there are tasks ready to run,
|
||||
those tasks have all their dependencies met, and the thread threshold has not been
|
||||
exceeded.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is worth noting that you can greatly speed up the build time by properly setting
|
||||
the <filename>BB_NUMBER_THREADS</filename> variable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As each task completes, a timestamp is written to the directory specified by the
|
||||
<link linkend='var-bb-STAMP'><filename>STAMP</filename></link> variable.
|
||||
On subsequent runs, BitBake looks in the build directory within
|
||||
<filename>tmp/stamps</filename> and does not rerun
|
||||
tasks that are already completed unless a timestamp is found to be invalid.
|
||||
Currently, invalid timestamps are only considered on a per
|
||||
recipe file basis.
|
||||
So, for example, if the configure stamp has a timestamp greater than the
|
||||
compile timestamp for a given target, then the compile task would rerun.
|
||||
Running the compile task again, however, has no effect on other providers
|
||||
that depend on that target.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The exact format of the stamps is partly configurable.
|
||||
In modern versions of BitBake, a hash is appended to the
|
||||
stamp so that if the configuration changes, the stamp becomes
|
||||
invalid and the task is automatically rerun.
|
||||
This hash, or signature used, is governed by the signature policy
|
||||
that is configured (see the
|
||||
"<link linkend='checksums'>Checksums (Signatures)</link>"
|
||||
section for information).
|
||||
It is also possible to append extra metadata to the stamp using
|
||||
the <filename>[stamp-extra-info]</filename> task flag.
|
||||
For example, OpenEmbedded uses this flag to make some tasks machine-specific.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
Some tasks are marked as "nostamp" tasks.
|
||||
No timestamp file is created when these tasks are run.
|
||||
Consequently, "nostamp" tasks are always rerun.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
For more information on tasks, see the
|
||||
"<link linkend='tasks'>Tasks</link>" section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='executing-tasks'>
|
||||
<title>Executing Tasks</title>
|
||||
|
||||
<para>
|
||||
Tasks can be either a shell task or a Python task.
|
||||
For shell tasks, BitBake writes a shell script to
|
||||
<filename>${</filename><link linkend='var-bb-T'><filename>T</filename></link><filename>}/run.do_taskname.pid</filename>
|
||||
and then executes the script.
|
||||
The generated shell script contains all the exported variables,
|
||||
and the shell functions with all variables expanded.
|
||||
Output from the shell script goes to the file
|
||||
<filename>${T}/log.do_taskname.pid</filename>.
|
||||
Looking at the expanded shell functions in the run file and
|
||||
the output in the log files is a useful debugging technique.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For Python tasks, BitBake executes the task internally and logs
|
||||
information to the controlling terminal.
|
||||
Future versions of BitBake will write the functions to files
|
||||
similar to the way shell tasks are handled.
|
||||
Logging will be handled in a way similar to shell tasks as well.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The order in which BitBake runs the tasks is controlled by its
|
||||
task scheduler.
|
||||
It is possible to configure the scheduler and define custom
|
||||
implementations for specific use cases.
|
||||
For more information, see these variables that control the
|
||||
behavior:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_SCHEDULER'><filename>BB_SCHEDULER</filename></link>
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<link linkend='var-bb-BB_SCHEDULERS'><filename>BB_SCHEDULERS</filename></link>
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
It is possible to have functions run before and after a task's main
|
||||
function.
|
||||
This is done using the <filename>[prefuncs]</filename>
|
||||
and <filename>[postfuncs]</filename> flags of the task
|
||||
that lists the functions to run.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='checksums'>
|
||||
<title>Checksums (Signatures)</title>
|
||||
|
||||
<para>
|
||||
A checksum is a unique signature of a task's inputs.
|
||||
The signature of a task can be used to determine if a task
|
||||
needs to be run.
|
||||
Because it is a change in a task's inputs that triggers running
|
||||
the task, BitBake needs to detect all the inputs to a given task.
|
||||
For shell tasks, this turns out to be fairly easy because
|
||||
BitBake generates a "run" shell script for each task and
|
||||
it is possible to create a checksum that gives you a good idea of when
|
||||
the task's data changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To complicate the problem, some things should not be included in
|
||||
the checksum.
|
||||
First, there is the actual specific build path of a given task -
|
||||
the working directory.
|
||||
It does not matter if the working directory changes because it should not
|
||||
affect the output for target packages.
|
||||
The simplistic approach for excluding the working directory is to set
|
||||
it to some fixed value and create the checksum for the "run" script.
|
||||
BitBake goes one step better and uses the
|
||||
<link linkend='var-bb-BB_HASHBASE_WHITELIST'><filename>BB_HASHBASE_WHITELIST</filename></link>
|
||||
variable to define a list of variables that should never be included
|
||||
when generating the signatures.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Another problem results from the "run" scripts containing functions that
|
||||
might or might not get called.
|
||||
The incremental build solution contains code that figures out dependencies
|
||||
between shell functions.
|
||||
This code is used to prune the "run" scripts down to the minimum set,
|
||||
thereby alleviating this problem and making the "run" scripts much more
|
||||
readable as a bonus.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So far we have solutions for shell scripts.
|
||||
What about Python tasks?
|
||||
The same approach applies even though these tasks are more difficult.
|
||||
The process needs to figure out what variables a Python function accesses
|
||||
and what functions it calls.
|
||||
Again, the incremental build solution contains code that first figures out
|
||||
the variable and function dependencies, and then creates a checksum for the data
|
||||
used as the input to the task.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Like the working directory case, situations exist where dependencies
|
||||
should be ignored.
|
||||
For these cases, you can instruct the build process to ignore a dependency
|
||||
by using a line like the following:
|
||||
<literallayout class='monospaced'>
|
||||
PACKAGE_ARCHS[vardepsexclude] = "MACHINE"
|
||||
</literallayout>
|
||||
This example ensures that the <filename>PACKAGE_ARCHS</filename> variable does not
|
||||
depend on the value of <filename>MACHINE</filename>, even if it does reference it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Equally, there are cases where we need to add dependencies BitBake
|
||||
is not able to find.
|
||||
You can accomplish this by using a line like the following:
|
||||
<literallayout class='monospaced'>
|
||||
PACKAGE_ARCHS[vardeps] = "MACHINE"
|
||||
</literallayout>
|
||||
This example explicitly adds the <filename>MACHINE</filename> variable as a
|
||||
dependency for <filename>PACKAGE_ARCHS</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Consider a case with in-line Python, for example, where BitBake is not
|
||||
able to figure out dependencies.
|
||||
When running in debug mode (i.e. using <filename>-DDD</filename>), BitBake
|
||||
produces output when it discovers something for which it cannot figure out
|
||||
dependencies.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Thus far, this section has limited discussion to the direct inputs into a task.
|
||||
Information based on direct inputs is referred to as the "basehash" in the
|
||||
code.
|
||||
However, there is still the question of a task's indirect inputs - the
|
||||
things that were already built and present in the build directory.
|
||||
The checksum (or signature) for a particular task needs to add the hashes
|
||||
of all the tasks on which the particular task depends.
|
||||
Choosing which dependencies to add is a policy decision.
|
||||
However, the effect is to generate a master checksum that combines the basehash
|
||||
and the hashes of the task's dependencies.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At the code level, there are a variety of ways both the basehash and the
|
||||
dependent task hashes can be influenced.
|
||||
Within the BitBake configuration file, we can give BitBake some extra information
|
||||
to help it construct the basehash.
|
||||
The following statement effectively results in a list of global variable
|
||||
dependency excludes - variables never included in any checksum.
|
||||
This example uses variables from OpenEmbedded to help illustrate
|
||||
the concept:
|
||||
<literallayout class='monospaced'>
|
||||
BB_HASHBASE_WHITELIST ?= "TMPDIR FILE PATH PWD BB_TASKHASH BBPATH DL_DIR \
|
||||
SSTATE_DIR THISDIR FILESEXTRAPATHS FILE_DIRNAME HOME LOGNAME SHELL TERM \
|
||||
USER FILESPATH STAGING_DIR_HOST STAGING_DIR_TARGET COREBASE PRSERV_HOST \
|
||||
PRSERV_DUMPDIR PRSERV_DUMPFILE PRSERV_LOCKDOWN PARALLEL_MAKE \
|
||||
CCACHE_DIR EXTERNAL_TOOLCHAIN CCACHE CCACHE_DISABLE LICENSE_PATH SDKPKGSUFFIX"
|
||||
</literallayout>
|
||||
The previous example excludes the work directory, which is part of
|
||||
<filename>TMPDIR</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The rules for deciding which hashes of dependent tasks to include through
|
||||
dependency chains are more complex and are generally accomplished with a
|
||||
Python function.
|
||||
The code in <filename>meta/lib/oe/sstatesig.py</filename> shows two examples
|
||||
of this and also illustrates how you can insert your own policy into the system
|
||||
if so desired.
|
||||
This file defines the two basic signature generators OpenEmbedded-Core
|
||||
uses: "OEBasic" and "OEBasicHash".
|
||||
By default, there is a dummy "noop" signature handler enabled in BitBake.
|
||||
This means that behavior is unchanged from previous versions.
|
||||
<filename>OE-Core</filename> uses the "OEBasicHash" signature handler by default
|
||||
through this setting in the <filename>bitbake.conf</filename> file:
|
||||
<literallayout class='monospaced'>
|
||||
BB_SIGNATURE_HANDLER ?= "OEBasicHash"
|
||||
</literallayout>
|
||||
The "OEBasicHash" <filename>BB_SIGNATURE_HANDLER</filename> is the same as the
|
||||
"OEBasic" version but adds the task hash to the stamp files.
|
||||
This results in any metadata change that changes the task hash, automatically
|
||||
causing the task to be run again.
|
||||
This removes the need to bump
|
||||
<link linkend='var-bb-PR'><filename>PR</filename></link>
|
||||
values, and changes to metadata automatically ripple across the build.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is also worth noting that the end result of these signature generators is to
|
||||
make some dependency and hash information available to the build.
|
||||
This information includes:
|
||||
<itemizedlist>
|
||||
<listitem><para><filename>BB_BASEHASH_task-</filename><replaceable>taskname</replaceable>:
|
||||
The base hashes for each task in the recipe.
|
||||
</para></listitem>
|
||||
<listitem><para><filename>BB_BASEHASH_</filename><replaceable>filename</replaceable><filename>:</filename><replaceable>taskname</replaceable>:
|
||||
The base hashes for each dependent task.
|
||||
</para></listitem>
|
||||
<listitem><para><filename>BBHASHDEPS_</filename><replaceable>filename</replaceable><filename>:</filename><replaceable>taskname</replaceable>:
|
||||
The task dependencies for each task.
|
||||
</para></listitem>
|
||||
<listitem><para><filename>BB_TASKHASH</filename>:
|
||||
The hash of the currently running task.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is worth noting that BitBake's "-S" option lets you
|
||||
debug Bitbake's processing of signatures.
|
||||
The options passed to -S allow different debugging modes
|
||||
to be used, either using BitBake's own debug functions
|
||||
or possibly those defined in the metadata/signature handler
|
||||
itself.
|
||||
The simplest parameter to pass is "none", which causes a
|
||||
set of signature information to be written out into
|
||||
<filename>STAMPS_DIR</filename>
|
||||
corresponding to the targets specified.
|
||||
The other currently available parameter is "printdiff",
|
||||
which causes BitBake to try to establish the closest
|
||||
signature match it can (e.g. in the sstate cache) and then
|
||||
run <filename>bitbake-diffsigs</filename> over the matches
|
||||
to determine the stamps and delta where these two
|
||||
stamp trees diverge.
|
||||
<note>
|
||||
It is likely that future versions of BitBake will
|
||||
provide other signature handlers triggered through
|
||||
additional "-S" parameters.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can find more information on checksum metadata in the
|
||||
"<link linkend='task-checksums-and-setscene'>Task Checksums and Setscene</link>"
|
||||
section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='setscene'>
|
||||
<title>Setscene</title>
|
||||
|
||||
<para>
|
||||
The setscene process enables BitBake to handle "pre-built" artifacts.
|
||||
The ability to handle and reuse these artifacts allows BitBake
|
||||
the luxury of not having to build something from scratch every time.
|
||||
Instead, BitBake can use, when possible, existing build artifacts.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake needs to have reliable data indicating whether or not an
|
||||
artifact is compatible.
|
||||
Signatures, described in the previous section, provide an ideal
|
||||
way of representing whether an artifact is compatible.
|
||||
If a signature is the same, an object can be reused.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If an object can be reused, the problem then becomes how to
|
||||
replace a given task or set of tasks with the pre-built artifact.
|
||||
BitBake solves the problem with the "setscene" process.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When BitBake is asked to build a given target, before building anything,
|
||||
it first asks whether cached information is available for any of the
|
||||
targets it's building, or any of the intermediate targets.
|
||||
If cached information is available, BitBake uses this information instead of
|
||||
running the main tasks.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake first calls the function defined by the
|
||||
<link linkend='var-bb-BB_HASHCHECK_FUNCTION'><filename>BB_HASHCHECK_FUNCTION</filename></link>
|
||||
variable with a list of tasks and corresponding
|
||||
hashes it wants to build.
|
||||
This function is designed to be fast and returns a list
|
||||
of the tasks for which it believes in can obtain artifacts.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, for each of the tasks that were returned as possibilities,
|
||||
BitBake executes a setscene version of the task that the possible
|
||||
artifact covers.
|
||||
Setscene versions of a task have the string "_setscene" appended to the
|
||||
task name.
|
||||
So, for example, the task with the name <filename>xxx</filename> has
|
||||
a setscene task named <filename>xxx_setscene</filename>.
|
||||
The setscene version of the task executes and provides the necessary
|
||||
artifacts returning either success or failure.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As previously mentioned, an artifact can cover more than one task.
|
||||
For example, it is pointless to obtain a compiler if you
|
||||
already have the compiled binary.
|
||||
To handle this, BitBake calls the
|
||||
<link linkend='var-bb-BB_SETSCENE_DEPVALID'><filename>BB_SETSCENE_DEPVALID</filename></link>
|
||||
function for each successful setscene task to know whether or not it needs
|
||||
to obtain the dependencies of that task.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally, after all the setscene tasks have executed, BitBake calls the
|
||||
function listed in
|
||||
<link linkend='var-bb-BB_SETSCENE_VERIFY_FUNCTION2'><filename>BB_SETSCENE_VERIFY_FUNCTION2</filename></link>
|
||||
with the list of tasks BitBake thinks has been "covered".
|
||||
The metadata can then ensure that this list is correct and can
|
||||
inform BitBake that it wants specific tasks to be run regardless
|
||||
of the setscene result.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can find more information on setscene metadata in the
|
||||
"<link linkend='task-checksums-and-setscene'>Task Checksums and Setscene</link>"
|
||||
section.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,851 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
=====================
|
||||
File Download Support
|
||||
=====================
|
||||
|
||||
|
|
||||
|
||||
BitBake's fetch module is a standalone piece of library code that deals
|
||||
with the intricacies of downloading source code and files from remote
|
||||
systems. Fetching source code is one of the cornerstones of building
|
||||
software. As such, this module forms an important part of BitBake.
|
||||
|
||||
The current fetch module is called "fetch2" and refers to the fact that
|
||||
it is the second major version of the API. The original version is
|
||||
obsolete and has been removed from the codebase. Thus, in all cases,
|
||||
"fetch" refers to "fetch2" in this manual.
|
||||
|
||||
The Download (Fetch)
|
||||
====================
|
||||
|
||||
BitBake takes several steps when fetching source code or files. The
|
||||
fetcher codebase deals with two distinct processes in order: obtaining
|
||||
the files from somewhere (cached or otherwise) and then unpacking those
|
||||
files into a specific location and perhaps in a specific way. Getting
|
||||
and unpacking the files is often optionally followed by patching.
|
||||
Patching, however, is not covered by this module.
|
||||
|
||||
The code to execute the first part of this process, a fetch, looks
|
||||
something like the following::
|
||||
|
||||
src_uri = (d.getVar('SRC_URI') or "").split()
|
||||
fetcher = bb.fetch2.Fetch(src_uri, d)
|
||||
fetcher.download()
|
||||
|
||||
This code sets up an instance of the fetch class. The instance uses a
|
||||
space-separated list of URLs from the :term:`SRC_URI`
|
||||
variable and then calls the ``download`` method to download the files.
|
||||
|
||||
The instantiation of the fetch class is usually followed by::
|
||||
|
||||
rootdir = l.getVar('WORKDIR')
|
||||
fetcher.unpack(rootdir)
|
||||
|
||||
This code unpacks the downloaded files to the specified by ``WORKDIR``.
|
||||
|
||||
.. note::
|
||||
|
||||
For convenience, the naming in these examples matches the variables
|
||||
used by OpenEmbedded. If you want to see the above code in action,
|
||||
examine the OpenEmbedded class file ``base.bbclass``
|
||||
.
|
||||
|
||||
The :term:`SRC_URI` and ``WORKDIR`` variables are not hardcoded into the
|
||||
fetcher, since those fetcher methods can be (and are) called with
|
||||
different variable names. In OpenEmbedded for example, the shared state
|
||||
(sstate) code uses the fetch module to fetch the sstate files.
|
||||
|
||||
When the ``download()`` method is called, BitBake tries to resolve the
|
||||
URLs by looking for source files in a specific search order:
|
||||
|
||||
- *Pre-mirror Sites:* BitBake first uses pre-mirrors to try and find
|
||||
source files. These locations are defined using the
|
||||
:term:`PREMIRRORS` variable.
|
||||
|
||||
- *Source URI:* If pre-mirrors fail, BitBake uses the original URL (e.g
|
||||
from :term:`SRC_URI`).
|
||||
|
||||
- *Mirror Sites:* If fetch failures occur, BitBake next uses mirror
|
||||
locations as defined by the :term:`MIRRORS` variable.
|
||||
|
||||
For each URL passed to the fetcher, the fetcher calls the submodule that
|
||||
handles that particular URL type. This behavior can be the source of
|
||||
some confusion when you are providing URLs for the :term:`SRC_URI` variable.
|
||||
Consider the following two URLs::
|
||||
|
||||
https://git.yoctoproject.org/git/poky;protocol=git
|
||||
git://git.yoctoproject.org/git/poky;protocol=http
|
||||
|
||||
In the former case, the URL is passed to the ``wget`` fetcher, which does not
|
||||
understand "git". Therefore, the latter case is the correct form since the Git
|
||||
fetcher does know how to use HTTP as a transport.
|
||||
|
||||
Here are some examples that show commonly used mirror definitions::
|
||||
|
||||
PREMIRRORS ?= "\
|
||||
bzr://.*/.\* http://somemirror.org/sources/ \
|
||||
cvs://.*/.\* http://somemirror.org/sources/ \
|
||||
git://.*/.\* http://somemirror.org/sources/ \
|
||||
hg://.*/.\* http://somemirror.org/sources/ \
|
||||
osc://.*/.\* http://somemirror.org/sources/ \
|
||||
p4://.*/.\* http://somemirror.org/sources/ \
|
||||
svn://.*/.\* http://somemirror.org/sources/"
|
||||
|
||||
MIRRORS =+ "\
|
||||
ftp://.*/.\* http://somemirror.org/sources/ \
|
||||
http://.*/.\* http://somemirror.org/sources/ \
|
||||
https://.*/.\* http://somemirror.org/sources/"
|
||||
|
||||
It is useful to note that BitBake
|
||||
supports cross-URLs. It is possible to mirror a Git repository on an
|
||||
HTTP server as a tarball. This is what the ``git://`` mapping in the
|
||||
previous example does.
|
||||
|
||||
Since network accesses are slow, BitBake maintains a cache of files
|
||||
downloaded from the network. Any source files that are not local (i.e.
|
||||
downloaded from the Internet) are placed into the download directory,
|
||||
which is specified by the :term:`DL_DIR` variable.
|
||||
|
||||
File integrity is of key importance for reproducing builds. For
|
||||
non-local archive downloads, the fetcher code can verify SHA-256 and MD5
|
||||
checksums to ensure the archives have been downloaded correctly. You can
|
||||
specify these checksums by using the :term:`SRC_URI` variable with the
|
||||
appropriate varflags as follows::
|
||||
|
||||
SRC_URI[md5sum] = "value"
|
||||
SRC_URI[sha256sum] = "value"
|
||||
|
||||
You can also specify the checksums as
|
||||
parameters on the :term:`SRC_URI` as shown below::
|
||||
|
||||
SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"
|
||||
|
||||
If multiple URIs exist, you can specify the checksums either directly as
|
||||
in the previous example, or you can name the URLs. The following syntax
|
||||
shows how you name the URIs::
|
||||
|
||||
SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
|
||||
SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d
|
||||
|
||||
After a file has been downloaded and
|
||||
has had its checksum checked, a ".done" stamp is placed in :term:`DL_DIR`.
|
||||
BitBake uses this stamp during subsequent builds to avoid downloading or
|
||||
comparing a checksum for the file again.
|
||||
|
||||
.. note::
|
||||
|
||||
It is assumed that local storage is safe from data corruption. If
|
||||
this were not the case, there would be bigger issues to worry about.
|
||||
|
||||
If :term:`BB_STRICT_CHECKSUM` is set, any
|
||||
download without a checksum triggers an error message. The
|
||||
:term:`BB_NO_NETWORK` variable can be used to
|
||||
make any attempted network access a fatal error, which is useful for
|
||||
checking that mirrors are complete as well as other things.
|
||||
|
||||
If :term:`BB_CHECK_SSL_CERTS` is set to ``0`` then SSL certificate checking will
|
||||
be disabled. This variable defaults to ``1`` so SSL certificates are normally
|
||||
checked.
|
||||
|
||||
.. _bb-the-unpack:
|
||||
|
||||
The Unpack
|
||||
==========
|
||||
|
||||
The unpack process usually immediately follows the download. For all
|
||||
URLs except Git URLs, BitBake uses the common ``unpack`` method.
|
||||
|
||||
A number of parameters exist that you can specify within the URL to
|
||||
govern the behavior of the unpack stage:
|
||||
|
||||
- *unpack:* Controls whether the URL components are unpacked. If set to
|
||||
"1", which is the default, the components are unpacked. If set to
|
||||
"0", the unpack stage leaves the file alone. This parameter is useful
|
||||
when you want an archive to be copied in and not be unpacked.
|
||||
|
||||
- *dos:* Applies to ``.zip`` and ``.jar`` files and specifies whether
|
||||
to use DOS line ending conversion on text files.
|
||||
|
||||
- *striplevel:* Strip specified number of leading components (levels)
|
||||
from file names on extraction
|
||||
|
||||
- *subdir:* Unpacks the specific URL to the specified subdirectory
|
||||
within the root directory.
|
||||
|
||||
The unpack call automatically decompresses and extracts files with ".Z",
|
||||
".z", ".gz", ".xz", ".zip", ".jar", ".ipk", ".rpm". ".srpm", ".deb" and
|
||||
".bz2" extensions as well as various combinations of tarball extensions.
|
||||
|
||||
As mentioned, the Git fetcher has its own unpack method that is
|
||||
optimized to work with Git trees. Basically, this method works by
|
||||
cloning the tree into the final directory. The process is completed
|
||||
using references so that there is only one central copy of the Git
|
||||
metadata needed.
|
||||
|
||||
.. _bb-fetchers:
|
||||
|
||||
Fetchers
|
||||
========
|
||||
|
||||
As mentioned earlier, the URL prefix determines which fetcher submodule
|
||||
BitBake uses. Each submodule can support different URL parameters, which
|
||||
are described in the following sections.
|
||||
|
||||
.. _local-file-fetcher:
|
||||
|
||||
Local file fetcher (``file://``)
|
||||
--------------------------------
|
||||
|
||||
This submodule handles URLs that begin with ``file://``. The filename
|
||||
you specify within the URL can be either an absolute or relative path to
|
||||
a file. If the filename is relative, the contents of the
|
||||
:term:`FILESPATH` variable is used in the same way
|
||||
``PATH`` is used to find executables. If the file cannot be found, it is
|
||||
assumed that it is available in :term:`DL_DIR` by the
|
||||
time the ``download()`` method is called.
|
||||
|
||||
If you specify a directory, the entire directory is unpacked.
|
||||
|
||||
Here are a couple of example URLs, the first relative and the second
|
||||
absolute::
|
||||
|
||||
SRC_URI = "file://relativefile.patch"
|
||||
SRC_URI = "file:///Users/ich/very_important_software"
|
||||
|
||||
.. _http-ftp-fetcher:
|
||||
|
||||
HTTP/FTP wget fetcher (``http://``, ``ftp://``, ``https://``)
|
||||
-------------------------------------------------------------
|
||||
|
||||
This fetcher obtains files from web and FTP servers. Internally, the
|
||||
fetcher uses the wget utility.
|
||||
|
||||
The executable and parameters used are specified by the
|
||||
``FETCHCMD_wget`` variable, which defaults to sensible values. The
|
||||
fetcher supports a parameter "downloadfilename" that allows the name of
|
||||
the downloaded file to be specified. Specifying the name of the
|
||||
downloaded file is useful for avoiding collisions in
|
||||
:term:`DL_DIR` when dealing with multiple files that
|
||||
have the same name.
|
||||
|
||||
If a username and password are specified in the ``SRC_URI``, a Basic
|
||||
Authorization header will be added to each request, including across redirects.
|
||||
To instead limit the Authorization header to the first request, add
|
||||
"redirectauth=0" to the list of parameters.
|
||||
|
||||
Some example URLs are as follows::
|
||||
|
||||
SRC_URI = "http://oe.handhelds.org/not_there.aac"
|
||||
SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
|
||||
SRC_URI = "ftp://you@oe.handhelds.org/home/you/secret.plan"
|
||||
|
||||
.. note::
|
||||
|
||||
Because URL parameters are delimited by semi-colons, this can
|
||||
introduce ambiguity when parsing URLs that also contain semi-colons,
|
||||
for example::
|
||||
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git;a=snapshot;h=a5dd47"
|
||||
|
||||
|
||||
Such URLs should should be modified by replacing semi-colons with '&'
|
||||
characters::
|
||||
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47"
|
||||
|
||||
|
||||
In most cases this should work. Treating semi-colons and '&' in
|
||||
queries identically is recommended by the World Wide Web Consortium
|
||||
(W3C). Note that due to the nature of the URL, you may have to
|
||||
specify the name of the downloaded file as well::
|
||||
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47;downloadfilename=myfile.bz2"
|
||||
|
||||
|
||||
.. _cvs-fetcher:
|
||||
|
||||
CVS fetcher (``(cvs://``)
|
||||
-------------------------
|
||||
|
||||
This submodule handles checking out files from the CVS version control
|
||||
system. You can configure it using a number of different variables:
|
||||
|
||||
- :term:`FETCHCMD_cvs <FETCHCMD>`: The name of the executable to use when running
|
||||
the ``cvs`` command. This name is usually "cvs".
|
||||
|
||||
- :term:`SRCDATE`: The date to use when fetching the CVS source code. A
|
||||
special value of "now" causes the checkout to be updated on every
|
||||
build.
|
||||
|
||||
- :term:`CVSDIR`: Specifies where a temporary
|
||||
checkout is saved. The location is often ``DL_DIR/cvs``.
|
||||
|
||||
- CVS_PROXY_HOST: The name to use as a "proxy=" parameter to the
|
||||
``cvs`` command.
|
||||
|
||||
- CVS_PROXY_PORT: The port number to use as a "proxyport="
|
||||
parameter to the ``cvs`` command.
|
||||
|
||||
As well as the standard username and password URL syntax, you can also
|
||||
configure the fetcher with various URL parameters:
|
||||
|
||||
The supported parameters are as follows:
|
||||
|
||||
- *"method":* The protocol over which to communicate with the CVS
|
||||
server. By default, this protocol is "pserver". If "method" is set to
|
||||
"ext", BitBake examines the "rsh" parameter and sets ``CVS_RSH``. You
|
||||
can use "dir" for local directories.
|
||||
|
||||
- *"module":* Specifies the module to check out. You must supply this
|
||||
parameter.
|
||||
|
||||
- *"tag":* Describes which CVS TAG should be used for the checkout. By
|
||||
default, the TAG is empty.
|
||||
|
||||
- *"date":* Specifies a date. If no "date" is specified, the
|
||||
:term:`SRCDATE` of the configuration is used to
|
||||
checkout a specific date. The special value of "now" causes the
|
||||
checkout to be updated on every build.
|
||||
|
||||
- *"localdir":* Used to rename the module. Effectively, you are
|
||||
renaming the output directory to which the module is unpacked. You
|
||||
are forcing the module into a special directory relative to
|
||||
:term:`CVSDIR`.
|
||||
|
||||
- *"rsh":* Used in conjunction with the "method" parameter.
|
||||
|
||||
- *"scmdata":* Causes the CVS metadata to be maintained in the tarball
|
||||
the fetcher creates when set to "keep". The tarball is expanded into
|
||||
the work directory. By default, the CVS metadata is removed.
|
||||
|
||||
- *"fullpath":* Controls whether the resulting checkout is at the
|
||||
module level, which is the default, or is at deeper paths.
|
||||
|
||||
- *"norecurse":* Causes the fetcher to only checkout the specified
|
||||
directory with no recurse into any subdirectories.
|
||||
|
||||
- *"port":* The port to which the CVS server connects.
|
||||
|
||||
Some example URLs are as follows::
|
||||
|
||||
SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
|
||||
SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
|
||||
|
||||
.. _svn-fetcher:
|
||||
|
||||
Subversion (SVN) Fetcher (``svn://``)
|
||||
-------------------------------------
|
||||
|
||||
This fetcher submodule fetches code from the Subversion source control
|
||||
system. The executable used is specified by ``FETCHCMD_svn``, which
|
||||
defaults to "svn". The fetcher's temporary working directory is set by
|
||||
:term:`SVNDIR`, which is usually ``DL_DIR/svn``.
|
||||
|
||||
The supported parameters are as follows:
|
||||
|
||||
- *"module":* The name of the svn module to checkout. You must provide
|
||||
this parameter. You can think of this parameter as the top-level
|
||||
directory of the repository data you want.
|
||||
|
||||
- *"path_spec":* A specific directory in which to checkout the
|
||||
specified svn module.
|
||||
|
||||
- *"protocol":* The protocol to use, which defaults to "svn". If
|
||||
"protocol" is set to "svn+ssh", the "ssh" parameter is also used.
|
||||
|
||||
- *"rev":* The revision of the source code to checkout.
|
||||
|
||||
- *"scmdata":* Causes the ".svn" directories to be available during
|
||||
compile-time when set to "keep". By default, these directories are
|
||||
removed.
|
||||
|
||||
- *"ssh":* An optional parameter used when "protocol" is set to
|
||||
"svn+ssh". You can use this parameter to specify the ssh program used
|
||||
by svn.
|
||||
|
||||
- *"transportuser":* When required, sets the username for the
|
||||
transport. By default, this parameter is empty. The transport
|
||||
username is different than the username used in the main URL, which
|
||||
is passed to the subversion command.
|
||||
|
||||
Following are three examples using svn::
|
||||
|
||||
SRC_URI = "svn://myrepos/proj1;module=vip;protocol=http;rev=667"
|
||||
SRC_URI = "svn://myrepos/proj1;module=opie;protocol=svn+ssh"
|
||||
SRC_URI = "svn://myrepos/proj1;module=trunk;protocol=http;path_spec=${MY_DIR}/proj1"
|
||||
|
||||
.. _git-fetcher:
|
||||
|
||||
Git Fetcher (``git://``)
|
||||
------------------------
|
||||
|
||||
This fetcher submodule fetches code from the Git source control system.
|
||||
The fetcher works by creating a bare clone of the remote into
|
||||
:term:`GITDIR`, which is usually ``DL_DIR/git2``. This
|
||||
bare clone is then cloned into the work directory during the unpack
|
||||
stage when a specific tree is checked out. This is done using alternates
|
||||
and by reference to minimize the amount of duplicate data on the disk
|
||||
and make the unpack process fast. The executable used can be set with
|
||||
``FETCHCMD_git``.
|
||||
|
||||
This fetcher supports the following parameters:
|
||||
|
||||
- *"protocol":* The protocol used to fetch the files. The default is
|
||||
"git" when a hostname is set. If a hostname is not set, the Git
|
||||
protocol is "file". You can also use "http", "https", "ssh" and
|
||||
"rsync".
|
||||
|
||||
.. note::
|
||||
|
||||
When ``protocol`` is "ssh", the URL expected in :term:`SRC_URI` differs
|
||||
from the one that is typically passed to ``git clone`` command and provided
|
||||
by the Git server to fetch from. For example, the URL returned by GitLab
|
||||
server for ``mesa`` when cloning over SSH is
|
||||
``git@gitlab.freedesktop.org:mesa/mesa.git``, however the expected URL in
|
||||
:term:`SRC_URI` is the following::
|
||||
|
||||
SRC_URI = "git://git@gitlab.freedesktop.org/mesa/mesa.git;branch=main;protocol=ssh;..."
|
||||
|
||||
Note the ``:`` character changed for a ``/`` before the path to the project.
|
||||
|
||||
- *"nocheckout":* Tells the fetcher to not checkout source code when
|
||||
unpacking when set to "1". Set this option for the URL where there is
|
||||
a custom routine to checkout code. The default is "0".
|
||||
|
||||
- *"rebaseable":* Indicates that the upstream Git repository can be
|
||||
rebased. You should set this parameter to "1" if revisions can become
|
||||
detached from branches. In this case, the source mirror tarball is
|
||||
done per revision, which has a loss of efficiency. Rebasing the
|
||||
upstream Git repository could cause the current revision to disappear
|
||||
from the upstream repository. This option reminds the fetcher to
|
||||
preserve the local cache carefully for future use. The default value
|
||||
for this parameter is "0".
|
||||
|
||||
- *"nobranch":* Tells the fetcher to not check the SHA validation for
|
||||
the branch when set to "1". The default is "0". Set this option for
|
||||
the recipe that refers to the commit that is valid for any namespace
|
||||
(branch, tag, ...) instead of the branch.
|
||||
|
||||
- *"bareclone":* Tells the fetcher to clone a bare clone into the
|
||||
destination directory without checking out a working tree. Only the
|
||||
raw Git metadata is provided. This parameter implies the "nocheckout"
|
||||
parameter as well.
|
||||
|
||||
- *"branch":* The branch(es) of the Git tree to clone. Unless
|
||||
"nobranch" is set to "1", this is a mandatory parameter. The number of
|
||||
branch parameters must match the number of name parameters.
|
||||
|
||||
- *"rev":* The revision to use for the checkout. The default is
|
||||
"master".
|
||||
|
||||
- *"tag":* Specifies a tag to use for the checkout. To correctly
|
||||
resolve tags, BitBake must access the network. For that reason, tags
|
||||
are often not used. As far as Git is concerned, the "tag" parameter
|
||||
behaves effectively the same as the "rev" parameter.
|
||||
|
||||
- *"subpath":* Limits the checkout to a specific subpath of the tree.
|
||||
By default, the whole tree is checked out.
|
||||
|
||||
- *"destsuffix":* The name of the path in which to place the checkout.
|
||||
By default, the path is ``git/``.
|
||||
|
||||
- *"usehead":* Enables local ``git://`` URLs to use the current branch
|
||||
HEAD as the revision for use with ``AUTOREV``. The "usehead"
|
||||
parameter implies no branch and only works when the transfer protocol
|
||||
is ``file://``.
|
||||
|
||||
Here are some example URLs::
|
||||
|
||||
SRC_URI = "git://github.com/fronteed/icheck.git;protocol=https;branch=${PV};tag=${PV}"
|
||||
SRC_URI = "git://github.com/asciidoc/asciidoc-py;protocol=https;branch=main"
|
||||
SRC_URI = "git://git@gitlab.freedesktop.org/mesa/mesa.git;branch=main;protocol=ssh;..."
|
||||
|
||||
.. note::
|
||||
|
||||
When using ``git`` as the fetcher of the main source code of your software,
|
||||
``S`` should be set accordingly::
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
.. note::
|
||||
|
||||
Specifying passwords directly in ``git://`` urls is not supported.
|
||||
There are several reasons: :term:`SRC_URI` is often written out to logs and
|
||||
other places, and that could easily leak passwords; it is also all too
|
||||
easy to share metadata without removing passwords. SSH keys, ``~/.netrc``
|
||||
and ``~/.ssh/config`` files can be used as alternatives.
|
||||
|
||||
Using tags with the git fetcher may cause surprising behaviour. Bitbake needs to
|
||||
resolve the tag to a specific revision and to do that, it has to connect to and use
|
||||
the upstream repository. This is because the revision the tags point at can change and
|
||||
we've seen cases of this happening in well known public repositories. This can mean
|
||||
many more network connections than expected and recipes may be reparsed at every build.
|
||||
Source mirrors will also be bypassed as the upstream repository is the only source
|
||||
of truth to resolve the revision accurately. For these reasons, whilst the fetcher
|
||||
can support tags, we recommend being specific about revisions in recipes.
|
||||
|
||||
.. _gitsm-fetcher:
|
||||
|
||||
Git Submodule Fetcher (``gitsm://``)
|
||||
------------------------------------
|
||||
|
||||
This fetcher submodule inherits from the :ref:`Git
|
||||
fetcher<bitbake-user-manual/bitbake-user-manual-fetching:git fetcher
|
||||
(\`\`git://\`\`)>` and extends that fetcher's behavior by fetching a
|
||||
repository's submodules. :term:`SRC_URI` is passed to the Git fetcher as
|
||||
described in the :ref:`bitbake-user-manual/bitbake-user-manual-fetching:git
|
||||
fetcher (\`\`git://\`\`)` section.
|
||||
|
||||
.. note::
|
||||
|
||||
You must clean a recipe when switching between '``git://``' and
|
||||
'``gitsm://``' URLs.
|
||||
|
||||
The Git Submodules fetcher is not a complete fetcher implementation.
|
||||
The fetcher has known issues where it does not use the normal source
|
||||
mirroring infrastructure properly. Further, the submodule sources it
|
||||
fetches are not visible to the licensing and source archiving
|
||||
infrastructures.
|
||||
|
||||
.. _clearcase-fetcher:
|
||||
|
||||
ClearCase Fetcher (``ccrc://``)
|
||||
-------------------------------
|
||||
|
||||
This fetcher submodule fetches code from a
|
||||
`ClearCase <http://en.wikipedia.org/wiki/Rational_ClearCase>`__
|
||||
repository.
|
||||
|
||||
To use this fetcher, make sure your recipe has proper
|
||||
:term:`SRC_URI`, :term:`SRCREV`, and
|
||||
:term:`PV` settings. Here is an example::
|
||||
|
||||
SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
|
||||
SRCREV = "EXAMPLE_CLEARCASE_TAG"
|
||||
PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
|
||||
|
||||
The fetcher uses the ``rcleartool`` or
|
||||
``cleartool`` remote client, depending on which one is available.
|
||||
|
||||
Following are options for the :term:`SRC_URI` statement:
|
||||
|
||||
- *vob*: The name, which must include the prepending "/" character,
|
||||
of the ClearCase VOB. This option is required.
|
||||
|
||||
- *module*: The module, which must include the prepending "/"
|
||||
character, in the selected VOB.
|
||||
|
||||
.. note::
|
||||
|
||||
The module and vob options are combined to create the load rule in the
|
||||
view config spec. As an example, consider the vob and module values from
|
||||
the SRC_URI statement at the start of this section. Combining those values
|
||||
results in the following::
|
||||
|
||||
load /example_vob/example_module
|
||||
|
||||
- *proto*: The protocol, which can be either ``http`` or ``https``.
|
||||
|
||||
By default, the fetcher creates a configuration specification. If you
|
||||
want this specification written to an area other than the default, use
|
||||
the ``CCASE_CUSTOM_CONFIG_SPEC`` variable in your recipe to define where
|
||||
the specification is written.
|
||||
|
||||
.. note::
|
||||
|
||||
the SRCREV loses its functionality if you specify this variable. However,
|
||||
SRCREV is still used to label the archive after a fetch even though it does
|
||||
not define what is fetched.
|
||||
|
||||
Here are a couple of other behaviors worth mentioning:
|
||||
|
||||
- When using ``cleartool``, the login of ``cleartool`` is handled by
|
||||
the system. The login require no special steps.
|
||||
|
||||
- In order to use ``rcleartool`` with authenticated users, an
|
||||
"rcleartool login" is necessary before using the fetcher.
|
||||
|
||||
.. _perforce-fetcher:
|
||||
|
||||
Perforce Fetcher (``p4://``)
|
||||
----------------------------
|
||||
|
||||
This fetcher submodule fetches code from the
|
||||
`Perforce <https://www.perforce.com/>`__ source control system. The
|
||||
executable used is specified by ``FETCHCMD_p4``, which defaults to "p4".
|
||||
The fetcher's temporary working directory is set by
|
||||
:term:`P4DIR`, which defaults to "DL_DIR/p4".
|
||||
The fetcher does not make use of a perforce client, instead it
|
||||
relies on ``p4 files`` to retrieve a list of
|
||||
files and ``p4 print`` to transfer the content
|
||||
of those files locally.
|
||||
|
||||
To use this fetcher, make sure your recipe has proper
|
||||
:term:`SRC_URI`, :term:`SRCREV`, and
|
||||
:term:`PV` values. The p4 executable is able to use the
|
||||
config file defined by your system's ``P4CONFIG`` environment variable
|
||||
in order to define the Perforce server URL and port, username, and
|
||||
password if you do not wish to keep those values in a recipe itself. If
|
||||
you choose not to use ``P4CONFIG``, or to explicitly set variables that
|
||||
``P4CONFIG`` can contain, you can specify the ``P4PORT`` value, which is
|
||||
the server's URL and port number, and you can specify a username and
|
||||
password directly in your recipe within :term:`SRC_URI`.
|
||||
|
||||
Here is an example that relies on ``P4CONFIG`` to specify the server URL
|
||||
and port, username, and password, and fetches the Head Revision::
|
||||
|
||||
SRC_URI = "p4://example-depot/main/source/..."
|
||||
SRCREV = "${AUTOREV}"
|
||||
PV = "p4-${SRCPV}"
|
||||
S = "${WORKDIR}/p4"
|
||||
|
||||
Here is an example that specifies the server URL and port, username, and
|
||||
password, and fetches a Revision based on a Label::
|
||||
|
||||
P4PORT = "tcp:p4server.example.net:1666"
|
||||
SRC_URI = "p4://user:passwd@example-depot/main/source/..."
|
||||
SRCREV = "release-1.0"
|
||||
PV = "p4-${SRCPV}"
|
||||
S = "${WORKDIR}/p4"
|
||||
|
||||
.. note::
|
||||
|
||||
You should always set S to "${WORKDIR}/p4" in your recipe.
|
||||
|
||||
By default, the fetcher strips the depot location from the local file paths. In
|
||||
the above example, the content of ``example-depot/main/source/`` will be placed
|
||||
in ``${WORKDIR}/p4``. For situations where preserving parts of the remote depot
|
||||
paths locally is desirable, the fetcher supports two parameters:
|
||||
|
||||
- *"module":*
|
||||
The top-level depot location or directory to fetch. The value of this
|
||||
parameter can also point to a single file within the depot, in which case
|
||||
the local file path will include the module path.
|
||||
- *"remotepath":*
|
||||
When used with the value "``keep``", the fetcher will mirror the full depot
|
||||
paths locally for the specified location, even in combination with the
|
||||
``module`` parameter.
|
||||
|
||||
Here is an example use of the the ``module`` parameter::
|
||||
|
||||
SRC_URI = "p4://user:passwd@example-depot/main;module=source/..."
|
||||
|
||||
In this case, the content of the top-level directory ``source/`` will be fetched
|
||||
to ``${P4DIR}``, including the directory itself. The top-level directory will
|
||||
be accesible at ``${P4DIR}/source/``.
|
||||
|
||||
Here is an example use of the the ``remotepath`` parameter::
|
||||
|
||||
SRC_URI = "p4://user:passwd@example-depot/main;module=source/...;remotepath=keep"
|
||||
|
||||
In this case, the content of the top-level directory ``source/`` will be fetched
|
||||
to ``${P4DIR}``, but the complete depot paths will be mirrored locally. The
|
||||
top-level directory will be accessible at
|
||||
``${P4DIR}/example-depot/main/source/``.
|
||||
|
||||
.. _repo-fetcher:
|
||||
|
||||
Repo Fetcher (``repo://``)
|
||||
--------------------------
|
||||
|
||||
This fetcher submodule fetches code from ``google-repo`` source control
|
||||
system. The fetcher works by initiating and syncing sources of the
|
||||
repository into :term:`REPODIR`, which is usually
|
||||
``${DL_DIR}/repo``.
|
||||
|
||||
This fetcher supports the following parameters:
|
||||
|
||||
- *"protocol":* Protocol to fetch the repository manifest (default:
|
||||
git).
|
||||
|
||||
- *"branch":* Branch or tag of repository to get (default: master).
|
||||
|
||||
- *"manifest":* Name of the manifest file (default: ``default.xml``).
|
||||
|
||||
Here are some example URLs::
|
||||
|
||||
SRC_URI = "repo://REPOROOT;protocol=git;branch=some_branch;manifest=my_manifest.xml"
|
||||
SRC_URI = "repo://REPOROOT;protocol=file;branch=some_branch;manifest=my_manifest.xml"
|
||||
|
||||
.. _az-fetcher:
|
||||
|
||||
Az Fetcher (``az://``)
|
||||
--------------------------
|
||||
|
||||
This submodule fetches data from an
|
||||
`Azure Storage account <https://docs.microsoft.com/en-us/azure/storage/>`__ ,
|
||||
it inherits its functionality from the HTTP wget fetcher, but modifies its
|
||||
behavior to accomodate the usage of a
|
||||
`Shared Access Signature (SAS) <https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview>`__
|
||||
for non-public data.
|
||||
|
||||
Such functionality is set by the variable:
|
||||
|
||||
- :term:`AZ_SAS`: The Azure Storage Shared Access Signature provides secure
|
||||
delegate access to resources, if this variable is set, the Az Fetcher will
|
||||
use it when fetching artifacts from the cloud.
|
||||
|
||||
You can specify the AZ_SAS variable as shown below::
|
||||
|
||||
AZ_SAS = "se=2021-01-01&sp=r&sv=2018-11-09&sr=c&skoid=<skoid>&sig=<signature>"
|
||||
|
||||
Here is an example URL::
|
||||
|
||||
SRC_URI = "az://<azure-storage-account>.blob.core.windows.net/<foo_container>/<bar_file>"
|
||||
|
||||
It can also be used when setting mirrors definitions using the :term:`PREMIRRORS` variable.
|
||||
|
||||
.. _gcp-fetcher:
|
||||
|
||||
GCP Fetcher (``gs://``)
|
||||
--------------------------
|
||||
|
||||
This submodule fetches data from a
|
||||
`Google Cloud Storage Bucket <https://cloud.google.com/storage/docs/buckets>`__.
|
||||
It uses the `Google Cloud Storage Python Client <https://cloud.google.com/python/docs/reference/storage/latest>`__
|
||||
to check the status of objects in the bucket and download them.
|
||||
The use of the Python client makes it substantially faster than using command
|
||||
line tools such as gsutil.
|
||||
|
||||
The fetcher requires the Google Cloud Storage Python Client to be installed, along
|
||||
with the gsutil tool.
|
||||
|
||||
The fetcher requires that the machine has valid credentials for accessing the
|
||||
chosen bucket. Instructions for authentication can be found in the
|
||||
`Google Cloud documentation <https://cloud.google.com/docs/authentication/provide-credentials-adc#local-dev>`__.
|
||||
|
||||
If it used from the OpenEmbedded build system, the fetcher can be used for
|
||||
fetching sstate artifacts from a GCS bucket by specifying the
|
||||
``SSTATE_MIRRORS`` variable as shown below::
|
||||
|
||||
SSTATE_MIRRORS ?= "\
|
||||
file://.* gs://<bucket name>/PATH \
|
||||
"
|
||||
|
||||
The fetcher can also be used in recipes::
|
||||
|
||||
SRC_URI = "gs://<bucket name>/<foo_container>/<bar_file>"
|
||||
|
||||
However, the checksum of the file should be also be provided::
|
||||
|
||||
SRC_URI[sha256sum] = "<sha256 string>"
|
||||
|
||||
.. _crate-fetcher:
|
||||
|
||||
Crate Fetcher (``crate://``)
|
||||
----------------------------
|
||||
|
||||
This submodule fetches code for
|
||||
`Rust language "crates" <https://doc.rust-lang.org/reference/glossary.html?highlight=crate#crate>`__
|
||||
corresponding to Rust libraries and programs to compile. Such crates are typically shared
|
||||
on https://crates.io/ but this fetcher supports other crate registries too.
|
||||
|
||||
The format for the :term:`SRC_URI` setting must be::
|
||||
|
||||
SRC_URI = "crate://REGISTRY/NAME/VERSION"
|
||||
|
||||
Here is an example URL::
|
||||
|
||||
SRC_URI = "crate://crates.io/glob/0.2.11"
|
||||
|
||||
.. _npm-fetcher:
|
||||
|
||||
NPM Fetcher (``npm://``)
|
||||
------------------------
|
||||
|
||||
This submodule fetches source code from an
|
||||
`NPM <https://en.wikipedia.org/wiki/Npm_(software)>`__
|
||||
Javascript package registry.
|
||||
|
||||
The format for the :term:`SRC_URI` setting must be::
|
||||
|
||||
SRC_URI = "npm://some.registry.url;ParameterA=xxx;ParameterB=xxx;..."
|
||||
|
||||
This fetcher supports the following parameters:
|
||||
|
||||
- *"package":* The NPM package name. This is a mandatory parameter.
|
||||
|
||||
- *"version":* The NPM package version. This is a mandatory parameter.
|
||||
|
||||
- *"downloadfilename":* Specifies the filename used when storing the downloaded file.
|
||||
|
||||
- *"destsuffix":* Specifies the directory to use to unpack the package (default: ``npm``).
|
||||
|
||||
Note that NPM fetcher only fetches the package source itself. The dependencies
|
||||
can be fetched through the `npmsw-fetcher`_.
|
||||
|
||||
Here is an example URL with both fetchers::
|
||||
|
||||
SRC_URI = " \
|
||||
npm://registry.npmjs.org/;package=cute-files;version=${PV} \
|
||||
npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json \
|
||||
"
|
||||
|
||||
See :yocto_docs:`Creating Node Package Manager (NPM) Packages
|
||||
</dev-manual/packages.html#creating-node-package-manager-npm-packages>`
|
||||
in the Yocto Project manual for details about using
|
||||
:yocto_docs:`devtool <https://docs.yoctoproject.org/ref-manual/devtool-reference.html>`
|
||||
to automatically create a recipe from an NPM URL.
|
||||
|
||||
.. _npmsw-fetcher:
|
||||
|
||||
NPM shrinkwrap Fetcher (``npmsw://``)
|
||||
-------------------------------------
|
||||
|
||||
This submodule fetches source code from an
|
||||
`NPM shrinkwrap <https://docs.npmjs.com/cli/v8/commands/npm-shrinkwrap>`__
|
||||
description file, which lists the dependencies
|
||||
of an NPM package while locking their versions.
|
||||
|
||||
The format for the :term:`SRC_URI` setting must be::
|
||||
|
||||
SRC_URI = "npmsw://some.registry.url;ParameterA=xxx;ParameterB=xxx;..."
|
||||
|
||||
This fetcher supports the following parameters:
|
||||
|
||||
- *"dev":* Set this parameter to ``1`` to install "devDependencies".
|
||||
|
||||
- *"destsuffix":* Specifies the directory to use to unpack the dependencies
|
||||
(``${S}`` by default).
|
||||
|
||||
Note that the shrinkwrap file can also be provided by the recipe for
|
||||
the package which has such dependencies, for example::
|
||||
|
||||
SRC_URI = " \
|
||||
npm://registry.npmjs.org/;package=cute-files;version=${PV} \
|
||||
npmsw://${THISDIR}/${BPN}/npm-shrinkwrap.json \
|
||||
"
|
||||
|
||||
Such a file can automatically be generated using
|
||||
:yocto_docs:`devtool <https://docs.yoctoproject.org/ref-manual/devtool-reference.html>`
|
||||
as described in the :yocto_docs:`Creating Node Package Manager (NPM) Packages
|
||||
</dev-manual/packages.html#creating-node-package-manager-npm-packages>`
|
||||
section of the Yocto Project.
|
||||
|
||||
Other Fetchers
|
||||
--------------
|
||||
|
||||
Fetch submodules also exist for the following:
|
||||
|
||||
- Bazaar (``bzr://``)
|
||||
|
||||
- Mercurial (``hg://``)
|
||||
|
||||
- OSC (``osc://``)
|
||||
|
||||
- S3 (``s3://``)
|
||||
|
||||
- Secure FTP (``sftp://``)
|
||||
|
||||
- Secure Shell (``ssh://``)
|
||||
|
||||
- Trees using Git Annex (``gitannex://``)
|
||||
|
||||
No documentation currently exists for these lesser used fetcher
|
||||
submodules. However, you might find the code helpful and readable.
|
||||
|
||||
Auto Revisions
|
||||
==============
|
||||
|
||||
We need to document ``AUTOREV`` and :term:`SRCREV_FORMAT` here.
|
||||
865
bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
Normal file
865
bitbake/doc/bitbake-user-manual/bitbake-user-manual-fetching.xml
Normal file
@@ -0,0 +1,865 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<chapter>
|
||||
<title>File Download Support</title>
|
||||
|
||||
<para>
|
||||
BitBake's fetch module is a standalone piece of library code
|
||||
that deals with the intricacies of downloading source code
|
||||
and files from remote systems.
|
||||
Fetching source code is one of the cornerstones of building software.
|
||||
As such, this module forms an important part of BitBake.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The current fetch module is called "fetch2" and refers to the
|
||||
fact that it is the second major version of the API.
|
||||
The original version is obsolete and has been removed from the codebase.
|
||||
Thus, in all cases, "fetch" refers to "fetch2" in this
|
||||
manual.
|
||||
</para>
|
||||
|
||||
<section id='the-download-fetch'>
|
||||
<title>The Download (Fetch)</title>
|
||||
|
||||
<para>
|
||||
BitBake takes several steps when fetching source code or files.
|
||||
The fetcher codebase deals with two distinct processes in order:
|
||||
obtaining the files from somewhere (cached or otherwise)
|
||||
and then unpacking those files into a specific location and
|
||||
perhaps in a specific way.
|
||||
Getting and unpacking the files is often optionally followed
|
||||
by patching.
|
||||
Patching, however, is not covered by this module.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The code to execute the first part of this process, a fetch,
|
||||
looks something like the following:
|
||||
<literallayout class='monospaced'>
|
||||
src_uri = (d.getVar('SRC_URI') or "").split()
|
||||
fetcher = bb.fetch2.Fetch(src_uri, d)
|
||||
fetcher.download()
|
||||
</literallayout>
|
||||
This code sets up an instance of the fetch class.
|
||||
The instance uses a space-separated list of URLs from the
|
||||
<link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
|
||||
variable and then calls the <filename>download</filename>
|
||||
method to download the files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The instantiation of the fetch class is usually followed by:
|
||||
<literallayout class='monospaced'>
|
||||
rootdir = l.getVar('WORKDIR')
|
||||
fetcher.unpack(rootdir)
|
||||
</literallayout>
|
||||
This code unpacks the downloaded files to the
|
||||
specified by <filename>WORKDIR</filename>.
|
||||
<note>
|
||||
For convenience, the naming in these examples matches
|
||||
the variables used by OpenEmbedded.
|
||||
If you want to see the above code in action, examine
|
||||
the OpenEmbedded class file <filename>base.bbclass</filename>.
|
||||
</note>
|
||||
The <filename>SRC_URI</filename> and <filename>WORKDIR</filename>
|
||||
variables are not hardcoded into the fetcher, since those fetcher
|
||||
methods can be (and are) called with different variable names.
|
||||
In OpenEmbedded for example, the shared state (sstate) code uses
|
||||
the fetch module to fetch the sstate files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When the <filename>download()</filename> method is called,
|
||||
BitBake tries to resolve the URLs by looking for source files
|
||||
in a specific search order:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Pre-mirror Sites:</emphasis>
|
||||
BitBake first uses pre-mirrors to try and find source files.
|
||||
These locations are defined using the
|
||||
<link linkend='var-bb-PREMIRRORS'><filename>PREMIRRORS</filename></link>
|
||||
variable.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Source URI:</emphasis>
|
||||
If pre-mirrors fail, BitBake uses the original URL (e.g from
|
||||
<filename>SRC_URI</filename>).
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Mirror Sites:</emphasis>
|
||||
If fetch failures occur, BitBake next uses mirror locations as
|
||||
defined by the
|
||||
<link linkend='var-bb-MIRRORS'><filename>MIRRORS</filename></link>
|
||||
variable.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For each URL passed to the fetcher, the fetcher
|
||||
calls the submodule that handles that particular URL type.
|
||||
This behavior can be the source of some confusion when you
|
||||
are providing URLs for the <filename>SRC_URI</filename>
|
||||
variable.
|
||||
Consider the following two URLs:
|
||||
<literallayout class='monospaced'>
|
||||
http://git.yoctoproject.org/git/poky;protocol=git
|
||||
git://git.yoctoproject.org/git/poky;protocol=http
|
||||
</literallayout>
|
||||
In the former case, the URL is passed to the
|
||||
<filename>wget</filename> fetcher, which does not
|
||||
understand "git".
|
||||
Therefore, the latter case is the correct form since the
|
||||
Git fetcher does know how to use HTTP as a transport.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here are some examples that show commonly used mirror
|
||||
definitions:
|
||||
<literallayout class='monospaced'>
|
||||
PREMIRRORS ?= "\
|
||||
bzr://.*/.* http://somemirror.org/sources/ \n \
|
||||
cvs://.*/.* http://somemirror.org/sources/ \n \
|
||||
git://.*/.* http://somemirror.org/sources/ \n \
|
||||
hg://.*/.* http://somemirror.org/sources/ \n \
|
||||
osc://.*/.* http://somemirror.org/sources/ \n \
|
||||
p4://.*/.* http://somemirror.org/sources/ \n \
|
||||
svn://.*/.* http://somemirror.org/sources/ \n"
|
||||
|
||||
MIRRORS =+ "\
|
||||
ftp://.*/.* http://somemirror.org/sources/ \n \
|
||||
http://.*/.* http://somemirror.org/sources/ \n \
|
||||
https://.*/.* http://somemirror.org/sources/ \n"
|
||||
</literallayout>
|
||||
It is useful to note that BitBake supports
|
||||
cross-URLs.
|
||||
It is possible to mirror a Git repository on an HTTP
|
||||
server as a tarball.
|
||||
This is what the <filename>git://</filename> mapping in
|
||||
the previous example does.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Since network accesses are slow, Bitbake maintains a
|
||||
cache of files downloaded from the network.
|
||||
Any source files that are not local (i.e.
|
||||
downloaded from the Internet) are placed into the download
|
||||
directory, which is specified by the
|
||||
<link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
|
||||
variable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
File integrity is of key importance for reproducing builds.
|
||||
For non-local archive downloads, the fetcher code can verify
|
||||
SHA-256 and MD5 checksums to ensure the archives have been
|
||||
downloaded correctly.
|
||||
You can specify these checksums by using the
|
||||
<filename>SRC_URI</filename> variable with the appropriate
|
||||
varflags as follows:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI[md5sum] = "<replaceable>value</replaceable>"
|
||||
SRC_URI[sha256sum] = "<replaceable>value</replaceable>"
|
||||
</literallayout>
|
||||
You can also specify the checksums as parameters on the
|
||||
<filename>SRC_URI</filename> as shown below:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://example.com/foobar.tar.bz2;md5sum=4a8e0f237e961fd7785d19d07fdb994d"
|
||||
</literallayout>
|
||||
If multiple URIs exist, you can specify the checksums either
|
||||
directly as in the previous example, or you can name the URLs.
|
||||
The following syntax shows how you name the URIs:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://example.com/foobar.tar.bz2;name=foo"
|
||||
SRC_URI[foo.md5sum] = 4a8e0f237e961fd7785d19d07fdb994d
|
||||
</literallayout>
|
||||
After a file has been downloaded and has had its checksum checked,
|
||||
a ".done" stamp is placed in <filename>DL_DIR</filename>.
|
||||
BitBake uses this stamp during subsequent builds to avoid
|
||||
downloading or comparing a checksum for the file again.
|
||||
<note>
|
||||
It is assumed that local storage is safe from data corruption.
|
||||
If this were not the case, there would be bigger issues to worry about.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If
|
||||
<link linkend='var-bb-BB_STRICT_CHECKSUM'><filename>BB_STRICT_CHECKSUM</filename></link>
|
||||
is set, any download without a checksum triggers an
|
||||
error message.
|
||||
The
|
||||
<link linkend='var-bb-BB_NO_NETWORK'><filename>BB_NO_NETWORK</filename></link>
|
||||
variable can be used to make any attempted network access a fatal
|
||||
error, which is useful for checking that mirrors are complete
|
||||
as well as other things.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bb-the-unpack'>
|
||||
<title>The Unpack</title>
|
||||
|
||||
<para>
|
||||
The unpack process usually immediately follows the download.
|
||||
For all URLs except Git URLs, BitBake uses the common
|
||||
<filename>unpack</filename> method.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A number of parameters exist that you can specify within the
|
||||
URL to govern the behavior of the unpack stage:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>unpack:</emphasis>
|
||||
Controls whether the URL components are unpacked.
|
||||
If set to "1", which is the default, the components
|
||||
are unpacked.
|
||||
If set to "0", the unpack stage leaves the file alone.
|
||||
This parameter is useful when you want an archive to be
|
||||
copied in and not be unpacked.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>dos:</emphasis>
|
||||
Applies to <filename>.zip</filename> and
|
||||
<filename>.jar</filename> files and specifies whether to
|
||||
use DOS line ending conversion on text files.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>basepath:</emphasis>
|
||||
Instructs the unpack stage to strip the specified
|
||||
directories from the source path when unpacking.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>subdir:</emphasis>
|
||||
Unpacks the specific URL to the specified subdirectory
|
||||
within the root directory.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
The unpack call automatically decompresses and extracts files
|
||||
with ".Z", ".z", ".gz", ".xz", ".zip", ".jar", ".ipk", ".rpm".
|
||||
".srpm", ".deb" and ".bz2" extensions as well as various combinations
|
||||
of tarball extensions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As mentioned, the Git fetcher has its own unpack method that
|
||||
is optimized to work with Git trees.
|
||||
Basically, this method works by cloning the tree into the final
|
||||
directory.
|
||||
The process is completed using references so that there is
|
||||
only one central copy of the Git metadata needed.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bb-fetchers'>
|
||||
<title>Fetchers</title>
|
||||
|
||||
<para>
|
||||
As mentioned earlier, the URL prefix determines which
|
||||
fetcher submodule BitBake uses.
|
||||
Each submodule can support different URL parameters,
|
||||
which are described in the following sections.
|
||||
</para>
|
||||
|
||||
<section id='local-file-fetcher'>
|
||||
<title>Local file fetcher (<filename>file://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This submodule handles URLs that begin with
|
||||
<filename>file://</filename>.
|
||||
The filename you specify within the URL can be
|
||||
either an absolute or relative path to a file.
|
||||
If the filename is relative, the contents of the
|
||||
<link linkend='var-bb-FILESPATH'><filename>FILESPATH</filename></link>
|
||||
variable is used in the same way
|
||||
<filename>PATH</filename> is used to find executables.
|
||||
If the file cannot be found, it is assumed that it is available in
|
||||
<link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
|
||||
by the time the <filename>download()</filename> method is called.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you specify a directory, the entire directory is
|
||||
unpacked.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here are a couple of example URLs, the first relative and
|
||||
the second absolute:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "file://relativefile.patch"
|
||||
SRC_URI = "file:///Users/ich/very_important_software"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='http-ftp-fetcher'>
|
||||
<title>HTTP/FTP wget fetcher (<filename>http://</filename>, <filename>ftp://</filename>, <filename>https://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher obtains files from web and FTP servers.
|
||||
Internally, the fetcher uses the wget utility.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The executable and parameters used are specified by the
|
||||
<filename>FETCHCMD_wget</filename> variable, which defaults
|
||||
to sensible values.
|
||||
The fetcher supports a parameter "downloadfilename" that
|
||||
allows the name of the downloaded file to be specified.
|
||||
Specifying the name of the downloaded file is useful
|
||||
for avoiding collisions in
|
||||
<link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link>
|
||||
when dealing with multiple files that have the same name.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some example URLs are as follows:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://oe.handhelds.org/not_there.aac"
|
||||
SRC_URI = "ftp://oe.handhelds.org/not_there_as_well.aac"
|
||||
SRC_URI = "ftp://you@oe.handhelds.org/home/you/secret.plan"
|
||||
</literallayout>
|
||||
</para>
|
||||
<note>
|
||||
Because URL parameters are delimited by semi-colons, this can
|
||||
introduce ambiguity when parsing URLs that also contain semi-colons,
|
||||
for example:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git;a=snapshot;h=a5dd47"
|
||||
</literallayout>
|
||||
Such URLs should should be modified by replacing semi-colons with '&' characters:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47"
|
||||
</literallayout>
|
||||
In most cases this should work. Treating semi-colons and '&' in queries
|
||||
identically is recommended by the World Wide Web Consortium (W3C).
|
||||
Note that due to the nature of the URL, you may have to specify the name
|
||||
of the downloaded file as well:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "http://abc123.org/git/?p=gcc/gcc.git&a=snapshot&h=a5dd47;downloadfilename=myfile.bz2"
|
||||
</literallayout>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id='cvs-fetcher'>
|
||||
<title>CVS fetcher (<filename>(cvs://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This submodule handles checking out files from the
|
||||
CVS version control system.
|
||||
You can configure it using a number of different variables:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis><filename>FETCHCMD_cvs</filename>:</emphasis>
|
||||
The name of the executable to use when running
|
||||
the <filename>cvs</filename> command.
|
||||
This name is usually "cvs".
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>SRCDATE</filename>:</emphasis>
|
||||
The date to use when fetching the CVS source code.
|
||||
A special value of "now" causes the checkout to
|
||||
be updated on every build.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><link linkend='var-bb-CVSDIR'><filename>CVSDIR</filename></link>:</emphasis>
|
||||
Specifies where a temporary checkout is saved.
|
||||
The location is often <filename>DL_DIR/cvs</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>CVS_PROXY_HOST</filename>:</emphasis>
|
||||
The name to use as a "proxy=" parameter to the
|
||||
<filename>cvs</filename> command.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>CVS_PROXY_PORT</filename>:</emphasis>
|
||||
The port number to use as a "proxyport=" parameter to
|
||||
the <filename>cvs</filename> command.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
As well as the standard username and password URL syntax,
|
||||
you can also configure the fetcher with various URL parameters:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The supported parameters are as follows:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>"method":</emphasis>
|
||||
The protocol over which to communicate with the CVS
|
||||
server.
|
||||
By default, this protocol is "pserver".
|
||||
If "method" is set to "ext", BitBake examines the
|
||||
"rsh" parameter and sets <filename>CVS_RSH</filename>.
|
||||
You can use "dir" for local directories.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"module":</emphasis>
|
||||
Specifies the module to check out.
|
||||
You must supply this parameter.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"tag":</emphasis>
|
||||
Describes which CVS TAG should be used for
|
||||
the checkout.
|
||||
By default, the TAG is empty.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"date":</emphasis>
|
||||
Specifies a date.
|
||||
If no "date" is specified, the
|
||||
<link linkend='var-bb-SRCDATE'><filename>SRCDATE</filename></link>
|
||||
of the configuration is used to checkout a specific date.
|
||||
The special value of "now" causes the checkout to be
|
||||
updated on every build.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"localdir":</emphasis>
|
||||
Used to rename the module.
|
||||
Effectively, you are renaming the output directory
|
||||
to which the module is unpacked.
|
||||
You are forcing the module into a special
|
||||
directory relative to
|
||||
<link linkend='var-bb-CVSDIR'><filename>CVSDIR</filename></link>.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"rsh"</emphasis>
|
||||
Used in conjunction with the "method" parameter.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"scmdata":</emphasis>
|
||||
Causes the CVS metadata to be maintained in the tarball
|
||||
the fetcher creates when set to "keep".
|
||||
The tarball is expanded into the work directory.
|
||||
By default, the CVS metadata is removed.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"fullpath":</emphasis>
|
||||
Controls whether the resulting checkout is at the
|
||||
module level, which is the default, or is at deeper
|
||||
paths.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"norecurse":</emphasis>
|
||||
Causes the fetcher to only checkout the specified
|
||||
directory with no recurse into any subdirectories.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"port":</emphasis>
|
||||
The port to which the CVS server connects.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
Some example URLs are as follows:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "cvs://CVSROOT;module=mymodule;tag=some-version;method=ext"
|
||||
SRC_URI = "cvs://CVSROOT;module=mymodule;date=20060126;localdir=usethat"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='svn-fetcher'>
|
||||
<title>Subversion (SVN) Fetcher (<filename>svn://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule fetches code from the
|
||||
Subversion source control system.
|
||||
The executable used is specified by
|
||||
<filename>FETCHCMD_svn</filename>, which defaults
|
||||
to "svn".
|
||||
The fetcher's temporary working directory is set by
|
||||
<link linkend='var-bb-SVNDIR'><filename>SVNDIR</filename></link>,
|
||||
which is usually <filename>DL_DIR/svn</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The supported parameters are as follows:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>"module":</emphasis>
|
||||
The name of the svn module to checkout.
|
||||
You must provide this parameter.
|
||||
You can think of this parameter as the top-level
|
||||
directory of the repository data you want.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"path_spec":</emphasis>
|
||||
A specific directory in which to checkout the
|
||||
specified svn module.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"protocol":</emphasis>
|
||||
The protocol to use, which defaults to "svn".
|
||||
If "protocol" is set to "svn+ssh", the "ssh"
|
||||
parameter is also used.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"rev":</emphasis>
|
||||
The revision of the source code to checkout.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"scmdata":</emphasis>
|
||||
Causes the “.svn” directories to be available during
|
||||
compile-time when set to "keep".
|
||||
By default, these directories are removed.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"ssh":</emphasis>
|
||||
An optional parameter used when "protocol" is set
|
||||
to "svn+ssh".
|
||||
You can use this parameter to specify the ssh
|
||||
program used by svn.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"transportuser":</emphasis>
|
||||
When required, sets the username for the transport.
|
||||
By default, this parameter is empty.
|
||||
The transport username is different than the username
|
||||
used in the main URL, which is passed to the subversion
|
||||
command.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
Following are three examples using svn:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "svn://myrepos/proj1;module=vip;protocol=http;rev=667"
|
||||
SRC_URI = "svn://myrepos/proj1;module=opie;protocol=svn+ssh"
|
||||
SRC_URI = "svn://myrepos/proj1;module=trunk;protocol=http;path_spec=${MY_DIR}/proj1"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='git-fetcher'>
|
||||
<title>Git Fetcher (<filename>git://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule fetches code from the Git
|
||||
source control system.
|
||||
The fetcher works by creating a bare clone of the
|
||||
remote into
|
||||
<link linkend='var-bb-GITDIR'><filename>GITDIR</filename></link>,
|
||||
which is usually <filename>DL_DIR/git2</filename>.
|
||||
This bare clone is then cloned into the work directory during the
|
||||
unpack stage when a specific tree is checked out.
|
||||
This is done using alternates and by reference to
|
||||
minimize the amount of duplicate data on the disk and
|
||||
make the unpack process fast.
|
||||
The executable used can be set with
|
||||
<filename>FETCHCMD_git</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This fetcher supports the following parameters:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>"protocol":</emphasis>
|
||||
The protocol used to fetch the files.
|
||||
The default is "git" when a hostname is set.
|
||||
If a hostname is not set, the Git protocol is "file".
|
||||
You can also use "http", "https", "ssh" and "rsync".
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"nocheckout":</emphasis>
|
||||
Tells the fetcher to not checkout source code when
|
||||
unpacking when set to "1".
|
||||
Set this option for the URL where there is a custom
|
||||
routine to checkout code.
|
||||
The default is "0".
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"rebaseable":</emphasis>
|
||||
Indicates that the upstream Git repository can be rebased.
|
||||
You should set this parameter to "1" if
|
||||
revisions can become detached from branches.
|
||||
In this case, the source mirror tarball is done per
|
||||
revision, which has a loss of efficiency.
|
||||
Rebasing the upstream Git repository could cause the
|
||||
current revision to disappear from the upstream repository.
|
||||
This option reminds the fetcher to preserve the local cache
|
||||
carefully for future use.
|
||||
The default value for this parameter is "0".
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"nobranch":</emphasis>
|
||||
Tells the fetcher to not check the SHA validation
|
||||
for the branch when set to "1".
|
||||
The default is "0".
|
||||
Set this option for the recipe that refers to
|
||||
the commit that is valid for a tag instead of
|
||||
the branch.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"bareclone":</emphasis>
|
||||
Tells the fetcher to clone a bare clone into the
|
||||
destination directory without checking out a working tree.
|
||||
Only the raw Git metadata is provided.
|
||||
This parameter implies the "nocheckout" parameter as well.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"branch":</emphasis>
|
||||
The branch(es) of the Git tree to clone.
|
||||
If unset, this is assumed to be "master".
|
||||
The number of branch parameters much match the number of
|
||||
name parameters.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"rev":</emphasis>
|
||||
The revision to use for the checkout.
|
||||
The default is "master".
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"tag":</emphasis>
|
||||
Specifies a tag to use for the checkout.
|
||||
To correctly resolve tags, BitBake must access the
|
||||
network.
|
||||
For that reason, tags are often not used.
|
||||
As far as Git is concerned, the "tag" parameter behaves
|
||||
effectively the same as the "rev" parameter.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"subpath":</emphasis>
|
||||
Limits the checkout to a specific subpath of the tree.
|
||||
By default, the whole tree is checked out.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"destsuffix":</emphasis>
|
||||
The name of the path in which to place the checkout.
|
||||
By default, the path is <filename>git/</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>"usehead":</emphasis>
|
||||
Enables local <filename>git://</filename> URLs to use the
|
||||
current branch HEAD as the revision for use with
|
||||
<filename>AUTOREV</filename>.
|
||||
The "usehead" parameter implies no branch and only works
|
||||
when the transfer protocol is
|
||||
<filename>file://</filename>.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
Here are some example URLs:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "git://git.oe.handhelds.org/git/vip.git;tag=version-1"
|
||||
SRC_URI = "git://git.oe.handhelds.org/git/vip.git;protocol=http"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='gitsm-fetcher'>
|
||||
<title>Git Submodule Fetcher (<filename>gitsm://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule inherits from the
|
||||
<link linkend='git-fetcher'>Git fetcher</link> and extends
|
||||
that fetcher's behavior by fetching a repository's submodules.
|
||||
<link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>
|
||||
is passed to the Git fetcher as described in the
|
||||
"<link linkend='git-fetcher'>Git Fetcher (<filename>git://</filename>)</link>"
|
||||
section.
|
||||
<note>
|
||||
<title>Notes and Warnings</title>
|
||||
<para>
|
||||
You must clean a recipe when switching between
|
||||
'<filename>git://</filename>' and
|
||||
'<filename>gitsm://</filename>' URLs.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Git Submodules fetcher is not a complete fetcher
|
||||
implementation.
|
||||
The fetcher has known issues where it does not use the
|
||||
normal source mirroring infrastructure properly. Further,
|
||||
the submodule sources it fetches are not visible to the
|
||||
licensing and source archiving infrastructures.
|
||||
</para>
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='clearcase-fetcher'>
|
||||
<title>ClearCase Fetcher (<filename>ccrc://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule fetches code from a
|
||||
<ulink url='http://en.wikipedia.org/wiki/Rational_ClearCase'>ClearCase</ulink>
|
||||
repository.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To use this fetcher, make sure your recipe has proper
|
||||
<link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>,
|
||||
<link linkend='var-bb-SRCREV'><filename>SRCREV</filename></link>, and
|
||||
<link linkend='var-bb-PV'><filename>PV</filename></link> settings.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "ccrc://cc.example.org/ccrc;vob=/example_vob;module=/example_module"
|
||||
SRCREV = "EXAMPLE_CLEARCASE_TAG"
|
||||
PV = "${@d.getVar("SRCREV", False).replace("/", "+")}"
|
||||
</literallayout>
|
||||
The fetcher uses the <filename>rcleartool</filename> or
|
||||
<filename>cleartool</filename> remote client, depending on
|
||||
which one is available.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Following are options for the <filename>SRC_URI</filename>
|
||||
statement:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis><filename>vob</filename></emphasis>:
|
||||
The name, which must include the
|
||||
prepending "/" character, of the ClearCase VOB.
|
||||
This option is required.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>module</filename></emphasis>:
|
||||
The module, which must include the
|
||||
prepending "/" character, in the selected VOB.
|
||||
<note>
|
||||
The <filename>module</filename> and <filename>vob</filename>
|
||||
options are combined to create the <filename>load</filename> rule in
|
||||
the view config spec.
|
||||
As an example, consider the <filename>vob</filename> and
|
||||
<filename>module</filename> values from the
|
||||
<filename>SRC_URI</filename> statement at the start of this section.
|
||||
Combining those values results in the following:
|
||||
<literallayout class='monospaced'>
|
||||
load /example_vob/example_module
|
||||
</literallayout>
|
||||
</note>
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>proto</filename></emphasis>:
|
||||
The protocol, which can be either <filename>http</filename> or
|
||||
<filename>https</filename>.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, the fetcher creates a configuration specification.
|
||||
If you want this specification written to an area other than the default,
|
||||
use the <filename>CCASE_CUSTOM_CONFIG_SPEC</filename> variable
|
||||
in your recipe to define where the specification is written.
|
||||
<note>
|
||||
the <filename>SRCREV</filename> loses its functionality if you
|
||||
specify this variable.
|
||||
However, <filename>SRCREV</filename> is still used to label the
|
||||
archive after a fetch even though it does not define what is
|
||||
fetched.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here are a couple of other behaviors worth mentioning:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
When using <filename>cleartool</filename>, the login of
|
||||
<filename>cleartool</filename> is handled by the system.
|
||||
The login require no special steps.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
In order to use <filename>rcleartool</filename> with authenticated
|
||||
users, an "rcleartool login" is necessary before using the fetcher.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='perforce-fetcher'>
|
||||
<title>Perforce Fetcher (<filename>p4://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule fetches code from the
|
||||
<ulink url='https://www.perforce.com/'>Perforce</ulink>
|
||||
source control system.
|
||||
The executable used is specified by
|
||||
<filename>FETCHCMD_p4</filename>, which defaults
|
||||
to "p4".
|
||||
The fetcher's temporary working directory is set by
|
||||
<link linkend='var-bb-P4DIR'><filename>P4DIR</filename></link>,
|
||||
which defaults to "DL_DIR/p4".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To use this fetcher, make sure your recipe has proper
|
||||
<link linkend='var-bb-SRC_URI'><filename>SRC_URI</filename></link>,
|
||||
<link linkend='var-bb-SRCREV'><filename>SRCREV</filename></link>, and
|
||||
<link linkend='var-bb-PV'><filename>PV</filename></link> values.
|
||||
The p4 executable is able to use the config file defined by your
|
||||
system's <filename>P4CONFIG</filename> environment variable in
|
||||
order to define the Perforce server URL and port, username, and
|
||||
password if you do not wish to keep those values in a recipe
|
||||
itself.
|
||||
If you choose not to use <filename>P4CONFIG</filename>,
|
||||
or to explicitly set variables that <filename>P4CONFIG</filename>
|
||||
can contain, you can specify the <filename>P4PORT</filename> value,
|
||||
which is the server's URL and port number, and you can
|
||||
specify a username and password directly in your recipe within
|
||||
<filename>SRC_URI</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is an example that relies on <filename>P4CONFIG</filename>
|
||||
to specify the server URL and port, username, and password, and
|
||||
fetches the Head Revision:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "p4://example-depot/main/source/..."
|
||||
SRCREV = "${AUTOREV}"
|
||||
PV = "p4-${SRCPV}"
|
||||
S = "${WORKDIR}/p4"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is an example that specifies the server URL and port,
|
||||
username, and password, and fetches a Revision based on a Label:
|
||||
<literallayout class='monospaced'>
|
||||
P4PORT = "tcp:p4server.example.net:1666"
|
||||
SRC_URI = "p4://user:passwd@example-depot/main/source/..."
|
||||
SRCREV = "release-1.0"
|
||||
PV = "p4-${SRCPV}"
|
||||
S = "${WORKDIR}/p4"
|
||||
</literallayout>
|
||||
<note>
|
||||
You should always set <filename>S</filename>
|
||||
to <filename>"${WORKDIR}/p4"</filename> in your recipe.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='repo-fetcher'>
|
||||
<title>Repo Fetcher (<filename>repo://</filename>)</title>
|
||||
|
||||
<para>
|
||||
This fetcher submodule fetches code from
|
||||
<filename>google-repo</filename> source control system.
|
||||
The fetcher works by initiating and syncing sources of the
|
||||
repository into
|
||||
<link linkend='var-bb-REPODIR'><filename>REPODIR</filename></link>,
|
||||
which is usually
|
||||
<link linkend='var-bb-DL_DIR'><filename>DL_DIR</filename></link><filename>/repo</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This fetcher supports the following parameters:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
<emphasis>"protocol":</emphasis>
|
||||
Protocol to fetch the repository manifest (default: git).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<emphasis>"branch":</emphasis>
|
||||
Branch or tag of repository to get (default: master).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
<emphasis>"manifest":</emphasis>
|
||||
Name of the manifest file (default: <filename>default.xml</filename>).
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
Here are some example URLs:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI = "repo://REPOROOT;protocol=git;branch=some_branch;manifest=my_manifest.xml"
|
||||
SRC_URI = "repo://REPOROOT;protocol=file;branch=some_branch;manifest=my_manifest.xml"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='other-fetchers'>
|
||||
<title>Other Fetchers</title>
|
||||
|
||||
<para>
|
||||
Fetch submodules also exist for the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
Bazaar (<filename>bzr://</filename>)
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Trees using Git Annex (<filename>gitannex://</filename>)
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Secure FTP (<filename>sftp://</filename>)
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Secure Shell (<filename>ssh://</filename>)
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
OSC (<filename>osc://</filename>)
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Mercurial (<filename>hg://</filename>)
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
No documentation currently exists for these lesser used
|
||||
fetcher submodules.
|
||||
However, you might find the code helpful and readable.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='auto-revisions'>
|
||||
<title>Auto Revisions</title>
|
||||
|
||||
<para>
|
||||
We need to document <filename>AUTOREV</filename> and
|
||||
<filename>SRCREV_FORMAT</filename> here.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -1,408 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
===================
|
||||
Hello World Example
|
||||
===================
|
||||
|
||||
BitBake Hello World
|
||||
===================
|
||||
|
||||
The simplest example commonly used to demonstrate any new programming
|
||||
language or tool is the "`Hello
|
||||
World <http://en.wikipedia.org/wiki/Hello_world_program>`__" example.
|
||||
This appendix demonstrates, in tutorial form, Hello World within the
|
||||
context of BitBake. The tutorial describes how to create a new project
|
||||
and the applicable metadata files necessary to allow BitBake to build
|
||||
it.
|
||||
|
||||
Obtaining BitBake
|
||||
=================
|
||||
|
||||
See the :ref:`bitbake-user-manual/bitbake-user-manual-intro:obtaining bitbake` section for
|
||||
information on how to obtain BitBake. Once you have the source code on
|
||||
your machine, the BitBake directory appears as follows::
|
||||
|
||||
$ ls -al
|
||||
total 108
|
||||
drwxr-xr-x 9 fawkh 10000 4096 feb 24 12:10 .
|
||||
drwx------ 36 fawkh 10000 4096 mar 2 17:00 ..
|
||||
-rw-r--r-- 1 fawkh 10000 365 feb 24 12:10 AUTHORS
|
||||
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 bin
|
||||
-rw-r--r-- 1 fawkh 10000 16501 feb 24 12:10 ChangeLog
|
||||
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 classes
|
||||
drwxr-xr-x 2 fawkh 10000 4096 feb 24 12:10 conf
|
||||
drwxr-xr-x 5 fawkh 10000 4096 feb 24 12:10 contrib
|
||||
drwxr-xr-x 6 fawkh 10000 4096 feb 24 12:10 doc
|
||||
drwxr-xr-x 8 fawkh 10000 4096 mar 2 16:26 .git
|
||||
-rw-r--r-- 1 fawkh 10000 31 feb 24 12:10 .gitattributes
|
||||
-rw-r--r-- 1 fawkh 10000 392 feb 24 12:10 .gitignore
|
||||
drwxr-xr-x 13 fawkh 10000 4096 feb 24 12:11 lib
|
||||
-rw-r--r-- 1 fawkh 10000 1224 feb 24 12:10 LICENSE
|
||||
-rw-r--r-- 1 fawkh 10000 15394 feb 24 12:10 LICENSE.GPL-2.0-only
|
||||
-rw-r--r-- 1 fawkh 10000 1286 feb 24 12:10 LICENSE.MIT
|
||||
-rw-r--r-- 1 fawkh 10000 229 feb 24 12:10 MANIFEST.in
|
||||
-rw-r--r-- 1 fawkh 10000 2413 feb 24 12:10 README
|
||||
-rw-r--r-- 1 fawkh 10000 43 feb 24 12:10 toaster-requirements.txt
|
||||
-rw-r--r-- 1 fawkh 10000 2887 feb 24 12:10 TODO
|
||||
|
||||
At this point, you should have BitBake cloned to a directory that
|
||||
matches the previous listing except for dates and user names.
|
||||
|
||||
Setting Up the BitBake Environment
|
||||
==================================
|
||||
|
||||
First, you need to be sure that you can run BitBake. Set your working
|
||||
directory to where your local BitBake files are and run the following
|
||||
command::
|
||||
|
||||
$ ./bin/bitbake --version
|
||||
BitBake Build Tool Core version 2.3.1
|
||||
|
||||
The console output tells you what version
|
||||
you are running.
|
||||
|
||||
The recommended method to run BitBake is from a directory of your
|
||||
choice. To be able to run BitBake from any directory, you need to add
|
||||
the executable binary to your binary to your shell's environment
|
||||
``PATH`` variable. First, look at your current ``PATH`` variable by
|
||||
entering the following::
|
||||
|
||||
$ echo $PATH
|
||||
|
||||
Next, add the directory location
|
||||
for the BitBake binary to the ``PATH``. Here is an example that adds the
|
||||
``/home/scott-lenovo/bitbake/bin`` directory to the front of the
|
||||
``PATH`` variable::
|
||||
|
||||
$ export PATH=/home/scott-lenovo/bitbake/bin:$PATH
|
||||
|
||||
You should now be able to enter the ``bitbake`` command from the command
|
||||
line while working from any directory.
|
||||
|
||||
The Hello World Example
|
||||
=======================
|
||||
|
||||
The overall goal of this exercise is to build a complete "Hello World"
|
||||
example utilizing task and layer concepts. Because this is how modern
|
||||
projects such as OpenEmbedded and the Yocto Project utilize BitBake, the
|
||||
example provides an excellent starting point for understanding BitBake.
|
||||
|
||||
To help you understand how to use BitBake to build targets, the example
|
||||
starts with nothing but the ``bitbake`` command, which causes BitBake to
|
||||
fail and report problems. The example progresses by adding pieces to the
|
||||
build to eventually conclude with a working, minimal "Hello World"
|
||||
example.
|
||||
|
||||
While every attempt is made to explain what is happening during the
|
||||
example, the descriptions cannot cover everything. You can find further
|
||||
information throughout this manual. Also, you can actively participate
|
||||
in the :oe_lists:`/g/bitbake-devel`
|
||||
discussion mailing list about the BitBake build tool.
|
||||
|
||||
.. note::
|
||||
|
||||
This example was inspired by and drew heavily from
|
||||
`Mailing List post - The BitBake equivalent of "Hello, World!"
|
||||
<https://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html>`_.
|
||||
|
||||
As stated earlier, the goal of this example is to eventually compile
|
||||
"Hello World". However, it is unknown what BitBake needs and what you
|
||||
have to provide in order to achieve that goal. Recall that BitBake
|
||||
utilizes three types of metadata files:
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-intro:configuration files`,
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-intro:classes`, and
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-intro:recipes`.
|
||||
But where do they go? How does BitBake find
|
||||
them? BitBake's error messaging helps you answer these types of
|
||||
questions and helps you better understand exactly what is going on.
|
||||
|
||||
Following is the complete "Hello World" example.
|
||||
|
||||
#. **Create a Project Directory:** First, set up a directory for the
|
||||
"Hello World" project. Here is how you can do so in your home
|
||||
directory::
|
||||
|
||||
$ mkdir ~/hello
|
||||
$ cd ~/hello
|
||||
|
||||
This is the directory that
|
||||
BitBake will use to do all of its work. You can use this directory
|
||||
to keep all the metafiles needed by BitBake. Having a project
|
||||
directory is a good way to isolate your project.
|
||||
|
||||
#. **Run BitBake:** At this point, you have nothing but a project
|
||||
directory. Run the ``bitbake`` command and see what it does::
|
||||
|
||||
$ bitbake
|
||||
ERROR: The BBPATH variable is not set and bitbake did not find a conf/bblayers.conf file in the expected location.
|
||||
Maybe you accidentally invoked bitbake from the wrong directory?
|
||||
|
||||
When you run BitBake, it begins looking for metadata files. The
|
||||
:term:`BBPATH` variable is what tells BitBake where
|
||||
to look for those files. :term:`BBPATH` is not set and you need to set
|
||||
it. Without :term:`BBPATH`, BitBake cannot find any configuration files
|
||||
(``.conf``) or recipe files (``.bb``) at all. BitBake also cannot
|
||||
find the ``bitbake.conf`` file.
|
||||
|
||||
#. **Setting BBPATH:** For this example, you can set :term:`BBPATH` in
|
||||
the same manner that you set ``PATH`` earlier in the appendix. You
|
||||
should realize, though, that it is much more flexible to set the
|
||||
:term:`BBPATH` variable up in a configuration file for each project.
|
||||
|
||||
From your shell, enter the following commands to set and export the
|
||||
:term:`BBPATH` variable::
|
||||
|
||||
$ BBPATH="projectdirectory"
|
||||
$ export BBPATH
|
||||
|
||||
Use your actual project directory in the command. BitBake uses that
|
||||
directory to find the metadata it needs for your project.
|
||||
|
||||
.. note::
|
||||
|
||||
When specifying your project directory, do not use the tilde
|
||||
("~") character as BitBake does not expand that character as the
|
||||
shell would.
|
||||
|
||||
#. **Run BitBake:** Now that you have :term:`BBPATH` defined, run the
|
||||
``bitbake`` command again::
|
||||
|
||||
$ bitbake
|
||||
ERROR: Unable to parse /home/scott-lenovo/bitbake/lib/bb/parse/__init__.py
|
||||
Traceback (most recent call last):
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 127, in resolve_file(fn='conf/bitbake.conf', d=<bb.data_smart.DataSmart object at 0x7f22919a3df0>):
|
||||
if not newfn:
|
||||
> raise IOError(errno.ENOENT, "file %s not found in %s" % (fn, bbpath))
|
||||
fn = newfn
|
||||
FileNotFoundError: [Errno 2] file conf/bitbake.conf not found in <projectdirectory>
|
||||
|
||||
|
||||
This sample output shows that BitBake could not find the
|
||||
``conf/bitbake.conf`` file in the project directory. This file is
|
||||
the first thing BitBake must find in order to build a target. And,
|
||||
since the project directory for this example is empty, you need to
|
||||
provide a ``conf/bitbake.conf`` file.
|
||||
|
||||
#. **Creating conf/bitbake.conf:** The ``conf/bitbake.conf`` includes
|
||||
a number of configuration variables BitBake uses for metadata and
|
||||
recipe files. For this example, you need to create the file in your
|
||||
project directory and define some key BitBake variables. For more
|
||||
information on the ``bitbake.conf`` file, see
|
||||
https://git.openembedded.org/bitbake/tree/conf/bitbake.conf.
|
||||
|
||||
Use the following commands to create the ``conf`` directory in the
|
||||
project directory::
|
||||
|
||||
$ mkdir conf
|
||||
|
||||
From within the ``conf`` directory,
|
||||
use some editor to create the ``bitbake.conf`` so that it contains
|
||||
the following::
|
||||
|
||||
PN = "${@bb.parse.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
|
||||
|
||||
TMPDIR = "${TOPDIR}/tmp"
|
||||
CACHE = "${TMPDIR}/cache"
|
||||
STAMP = "${TMPDIR}/${PN}/stamps"
|
||||
T = "${TMPDIR}/${PN}/work"
|
||||
B = "${TMPDIR}/${PN}"
|
||||
|
||||
.. note::
|
||||
|
||||
Without a value for :term:`PN`, the variables :term:`STAMP`, :term:`T`, and :term:`B`, prevent more
|
||||
than one recipe from working. You can fix this by either setting :term:`PN` to
|
||||
have a value similar to what OpenEmbedded and BitBake use in the default
|
||||
``bitbake.conf`` file (see previous example). Or, by manually updating each
|
||||
recipe to set :term:`PN`. You will also need to include :term:`PN` as part of the :term:`STAMP`,
|
||||
:term:`T`, and :term:`B` variable definitions in the ``local.conf`` file.
|
||||
|
||||
The ``TMPDIR`` variable establishes a directory that BitBake uses
|
||||
for build output and intermediate files other than the cached
|
||||
information used by the
|
||||
:ref:`bitbake-user-manual/bitbake-user-manual-execution:setscene`
|
||||
process. Here, the ``TMPDIR`` directory is set to ``hello/tmp``.
|
||||
|
||||
.. tip::
|
||||
|
||||
You can always safely delete the tmp directory in order to rebuild a
|
||||
BitBake target. The build process creates the directory for you when you
|
||||
run BitBake.
|
||||
|
||||
For information about each of the other variables defined in this
|
||||
example, check :term:`PN`, :term:`TOPDIR`, :term:`CACHE`, :term:`STAMP`,
|
||||
:term:`T` or :term:`B` to take you to the definitions in the
|
||||
glossary.
|
||||
|
||||
#. **Run BitBake:** After making sure that the ``conf/bitbake.conf`` file
|
||||
exists, you can run the ``bitbake`` command again::
|
||||
|
||||
$ bitbake
|
||||
ERROR: Unable to parse /home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py
|
||||
Traceback (most recent call last):
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py", line 67, in inherit(files=['base'], fn='configuration INHERITs', lineno=0, d=<bb.data_smart.DataSmart object at 0x7fab6815edf0>):
|
||||
if not os.path.exists(file):
|
||||
> raise ParseError("Could not inherit file %s" % (file), fn, lineno)
|
||||
|
||||
bb.parse.ParseError: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
|
||||
|
||||
|
||||
In the sample output,
|
||||
BitBake could not find the ``classes/base.bbclass`` file. You need
|
||||
to create that file next.
|
||||
|
||||
#. **Creating classes/base.bbclass:** BitBake uses class files to
|
||||
provide common code and functionality. The minimally required class
|
||||
for BitBake is the ``classes/base.bbclass`` file. The ``base`` class
|
||||
is implicitly inherited by every recipe. BitBake looks for the class
|
||||
in the ``classes`` directory of the project (i.e ``hello/classes``
|
||||
in this example).
|
||||
|
||||
Create the ``classes`` directory as follows::
|
||||
|
||||
$ cd $HOME/hello
|
||||
$ mkdir classes
|
||||
|
||||
Move to the ``classes`` directory and then create the
|
||||
``base.bbclass`` file by inserting this single line::
|
||||
|
||||
addtask build
|
||||
|
||||
The minimal task that BitBake runs is the ``do_build`` task. This is
|
||||
all the example needs in order to build the project. Of course, the
|
||||
``base.bbclass`` can have much more depending on which build
|
||||
environments BitBake is supporting.
|
||||
|
||||
#. **Run BitBake:** After making sure that the ``classes/base.bbclass``
|
||||
file exists, you can run the ``bitbake`` command again::
|
||||
|
||||
$ bitbake
|
||||
Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
|
||||
|
||||
BitBake is finally reporting
|
||||
no errors. However, you can see that it really does not have
|
||||
anything to do. You need to create a recipe that gives BitBake
|
||||
something to do.
|
||||
|
||||
#. **Creating a Layer:** While it is not really necessary for such a
|
||||
small example, it is good practice to create a layer in which to
|
||||
keep your code separate from the general metadata used by BitBake.
|
||||
Thus, this example creates and uses a layer called "mylayer".
|
||||
|
||||
.. note::
|
||||
|
||||
You can find additional information on layers in the
|
||||
":ref:`bitbake-user-manual/bitbake-user-manual-intro:Layers`" section.
|
||||
|
||||
Minimally, you need a recipe file and a layer configuration file in
|
||||
your layer. The configuration file needs to be in the ``conf``
|
||||
directory inside the layer. Use these commands to set up the layer
|
||||
and the ``conf`` directory::
|
||||
|
||||
$ cd $HOME
|
||||
$ mkdir mylayer
|
||||
$ cd mylayer
|
||||
$ mkdir conf
|
||||
|
||||
Move to the ``conf`` directory and create a ``layer.conf`` file that has the
|
||||
following::
|
||||
|
||||
BBPATH .= ":${LAYERDIR}"
|
||||
BBFILES += "${LAYERDIR}/*.bb"
|
||||
BBFILE_COLLECTIONS += "mylayer"
|
||||
BBFILE_PATTERN_mylayer := "^${LAYERDIR_RE}/"
|
||||
LAYERSERIES_CORENAMES = "hello_world_example"
|
||||
LAYERSERIES_COMPAT_mylayer = "hello_world_example"
|
||||
|
||||
For information on these variables, click on :term:`BBFILES`,
|
||||
:term:`LAYERDIR`, :term:`BBFILE_COLLECTIONS`, :term:`BBFILE_PATTERN_mylayer <BBFILE_PATTERN>`
|
||||
or :term:`LAYERSERIES_COMPAT` to go to the definitions in the glossary.
|
||||
|
||||
.. note::
|
||||
|
||||
We are setting both ``LAYERSERIES_CORENAMES`` and :term:`LAYERSERIES_COMPAT` in this particular case, because we
|
||||
are using bitbake without OpenEmbedded.
|
||||
You should usually just use :term:`LAYERSERIES_COMPAT` to specify the OE-Core versions for which your layer
|
||||
is compatible, and add the meta-openembedded layer to your project.
|
||||
|
||||
You need to create the recipe file next. Inside your layer at the
|
||||
top-level, use an editor and create a recipe file named
|
||||
``printhello.bb`` that has the following::
|
||||
|
||||
DESCRIPTION = "Prints Hello World"
|
||||
PN = 'printhello'
|
||||
PV = '1'
|
||||
|
||||
python do_build() {
|
||||
bb.plain("********************");
|
||||
bb.plain("* *");
|
||||
bb.plain("* Hello, World! *");
|
||||
bb.plain("* *");
|
||||
bb.plain("********************");
|
||||
}
|
||||
|
||||
The recipe file simply provides
|
||||
a description of the recipe, the name, version, and the ``do_build``
|
||||
task, which prints out "Hello World" to the console. For more
|
||||
information on :term:`DESCRIPTION`, :term:`PN` or :term:`PV`
|
||||
follow the links to the glossary.
|
||||
|
||||
#. **Run BitBake With a Target:** Now that a BitBake target exists, run
|
||||
the command and provide that target::
|
||||
|
||||
$ cd $HOME/hello
|
||||
$ bitbake printhello
|
||||
ERROR: no recipe files to build, check your BBPATH and BBFILES?
|
||||
|
||||
Summary: There was 1 ERROR message shown, returning a non-zero exit code.
|
||||
|
||||
We have created the layer with the recipe and
|
||||
the layer configuration file but it still seems that BitBake cannot
|
||||
find the recipe. BitBake needs a ``conf/bblayers.conf`` that lists
|
||||
the layers for the project. Without this file, BitBake cannot find
|
||||
the recipe.
|
||||
|
||||
#. **Creating conf/bblayers.conf:** BitBake uses the
|
||||
``conf/bblayers.conf`` file to locate layers needed for the project.
|
||||
This file must reside in the ``conf`` directory of the project (i.e.
|
||||
``hello/conf`` for this example).
|
||||
|
||||
Set your working directory to the ``hello/conf`` directory and then
|
||||
create the ``bblayers.conf`` file so that it contains the following::
|
||||
|
||||
BBLAYERS ?= " \
|
||||
/home/<you>/mylayer \
|
||||
"
|
||||
|
||||
You need to provide your own information for ``you`` in the file.
|
||||
|
||||
#. **Run BitBake With a Target:** Now that you have supplied the
|
||||
``bblayers.conf`` file, run the ``bitbake`` command and provide the
|
||||
target::
|
||||
|
||||
$ bitbake printhello
|
||||
Loading cache: 100% |
|
||||
Loaded 0 entries from dependency cache.
|
||||
Parsing recipes: 100% |##################################################################################|
|
||||
Parsing of 1 .bb files complete (0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors.
|
||||
NOTE: Resolving any missing task queue dependencies
|
||||
Initialising tasks: 100% |###############################################################################|
|
||||
NOTE: No setscene tasks
|
||||
NOTE: Executing Tasks
|
||||
********************
|
||||
* *
|
||||
* Hello, World! *
|
||||
* *
|
||||
********************
|
||||
NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
|
||||
|
||||
.. note::
|
||||
|
||||
After the first execution, re-running bitbake printhello again will not
|
||||
result in a BitBake run that prints the same console output. The reason
|
||||
for this is that the first time the printhello.bb recipe's do_build task
|
||||
executes successfully, BitBake writes a stamp file for the task. Thus,
|
||||
the next time you attempt to run the task using that same bitbake
|
||||
command, BitBake notices the stamp and therefore determines that the task
|
||||
does not need to be re-run. If you delete the tmp directory or run
|
||||
bitbake -c clean printhello and then re-run the build, the "Hello,
|
||||
World!" message will be printed again.
|
||||
513
bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
Normal file
513
bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
Normal file
@@ -0,0 +1,513 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<appendix id='hello-world-example'>
|
||||
<title>Hello World Example</title>
|
||||
|
||||
<section id='bitbake-hello-world'>
|
||||
<title>BitBake Hello World</title>
|
||||
|
||||
<para>
|
||||
The simplest example commonly used to demonstrate any new
|
||||
programming language or tool is the
|
||||
"<ulink url="http://en.wikipedia.org/wiki/Hello_world_program">Hello World</ulink>"
|
||||
example.
|
||||
This appendix demonstrates, in tutorial form, Hello
|
||||
World within the context of BitBake.
|
||||
The tutorial describes how to create a new project
|
||||
and the applicable metadata files necessary to allow
|
||||
BitBake to build it.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='example-obtaining-bitbake'>
|
||||
<title>Obtaining BitBake</title>
|
||||
|
||||
<para>
|
||||
See the
|
||||
"<link linkend='obtaining-bitbake'>Obtaining BitBake</link>"
|
||||
section for information on how to obtain BitBake.
|
||||
Once you have the source code on your machine, the BitBake directory
|
||||
appears as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ ls -al
|
||||
total 100
|
||||
drwxrwxr-x. 9 wmat wmat 4096 Jan 31 13:44 .
|
||||
drwxrwxr-x. 3 wmat wmat 4096 Feb 4 10:45 ..
|
||||
-rw-rw-r--. 1 wmat wmat 365 Nov 26 04:55 AUTHORS
|
||||
drwxrwxr-x. 2 wmat wmat 4096 Nov 26 04:55 bin
|
||||
drwxrwxr-x. 4 wmat wmat 4096 Jan 31 13:44 build
|
||||
-rw-rw-r--. 1 wmat wmat 16501 Nov 26 04:55 ChangeLog
|
||||
drwxrwxr-x. 2 wmat wmat 4096 Nov 26 04:55 classes
|
||||
drwxrwxr-x. 2 wmat wmat 4096 Nov 26 04:55 conf
|
||||
drwxrwxr-x. 3 wmat wmat 4096 Nov 26 04:55 contrib
|
||||
-rw-rw-r--. 1 wmat wmat 17987 Nov 26 04:55 COPYING
|
||||
drwxrwxr-x. 3 wmat wmat 4096 Nov 26 04:55 doc
|
||||
-rw-rw-r--. 1 wmat wmat 69 Nov 26 04:55 .gitignore
|
||||
-rw-rw-r--. 1 wmat wmat 849 Nov 26 04:55 HEADER
|
||||
drwxrwxr-x. 5 wmat wmat 4096 Jan 31 13:44 lib
|
||||
-rw-rw-r--. 1 wmat wmat 195 Nov 26 04:55 MANIFEST.in
|
||||
-rw-rw-r--. 1 wmat wmat 2887 Nov 26 04:55 TODO
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At this point, you should have BitBake cloned to
|
||||
a directory that matches the previous listing except for
|
||||
dates and user names.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='setting-up-the-bitbake-environment'>
|
||||
<title>Setting Up the BitBake Environment</title>
|
||||
|
||||
<para>
|
||||
First, you need to be sure that you can run BitBake.
|
||||
Set your working directory to where your local BitBake
|
||||
files are and run the following command:
|
||||
<literallayout class='monospaced'>
|
||||
$ ./bin/bitbake --version
|
||||
BitBake Build Tool Core version 1.23.0, bitbake version 1.23.0
|
||||
</literallayout>
|
||||
The console output tells you what version you are running.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The recommended method to run BitBake is from a directory of your
|
||||
choice.
|
||||
To be able to run BitBake from any directory, you need to add the
|
||||
executable binary to your binary to your shell's environment
|
||||
<filename>PATH</filename> variable.
|
||||
First, look at your current <filename>PATH</filename> variable
|
||||
by entering the following:
|
||||
<literallayout class='monospaced'>
|
||||
$ echo $PATH
|
||||
</literallayout>
|
||||
Next, add the directory location for the BitBake binary to the
|
||||
<filename>PATH</filename>.
|
||||
Here is an example that adds the
|
||||
<filename>/home/scott-lenovo/bitbake/bin</filename> directory
|
||||
to the front of the <filename>PATH</filename> variable:
|
||||
<literallayout class='monospaced'>
|
||||
$ export PATH=/home/scott-lenovo/bitbake/bin:$PATH
|
||||
</literallayout>
|
||||
You should now be able to enter the <filename>bitbake</filename>
|
||||
command from the command line while working from any directory.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='the-hello-world-example'>
|
||||
<title>The Hello World Example</title>
|
||||
|
||||
<para>
|
||||
The overall goal of this exercise is to build a
|
||||
complete "Hello World" example utilizing task and layer
|
||||
concepts.
|
||||
Because this is how modern projects such as OpenEmbedded and
|
||||
the Yocto Project utilize BitBake, the example
|
||||
provides an excellent starting point for understanding
|
||||
BitBake.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To help you understand how to use BitBake to build targets,
|
||||
the example starts with nothing but the <filename>bitbake</filename>
|
||||
command, which causes BitBake to fail and report problems.
|
||||
The example progresses by adding pieces to the build to
|
||||
eventually conclude with a working, minimal "Hello World"
|
||||
example.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
While every attempt is made to explain what is happening during
|
||||
the example, the descriptions cannot cover everything.
|
||||
You can find further information throughout this manual.
|
||||
Also, you can actively participate in the
|
||||
<ulink url='http://lists.openembedded.org/mailman/listinfo/bitbake-devel'></ulink>
|
||||
discussion mailing list about the BitBake build tool.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
This example was inspired by and drew heavily from
|
||||
<ulink url="http://www.mail-archive.com/yocto@yoctoproject.org/msg09379.html">Mailing List post - The BitBake equivalent of "Hello, World!"</ulink>.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
As stated earlier, the goal of this example
|
||||
is to eventually compile "Hello World".
|
||||
However, it is unknown what BitBake needs and what you have
|
||||
to provide in order to achieve that goal.
|
||||
Recall that BitBake utilizes three types of metadata files:
|
||||
<link linkend='configuration-files'>Configuration Files</link>,
|
||||
<link linkend='classes'>Classes</link>, and
|
||||
<link linkend='recipes'>Recipes</link>.
|
||||
But where do they go?
|
||||
How does BitBake find them?
|
||||
BitBake's error messaging helps you answer these types of questions
|
||||
and helps you better understand exactly what is going on.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Following is the complete "Hello World" example.
|
||||
</para>
|
||||
|
||||
<orderedlist>
|
||||
<listitem><para><emphasis>Create a Project Directory:</emphasis>
|
||||
First, set up a directory for the "Hello World" project.
|
||||
Here is how you can do so in your home directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ mkdir ~/hello
|
||||
$ cd ~/hello
|
||||
</literallayout>
|
||||
This is the directory that BitBake will use to do all of
|
||||
its work.
|
||||
You can use this directory to keep all the metafiles needed
|
||||
by BitBake.
|
||||
Having a project directory is a good way to isolate your
|
||||
project.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake:</emphasis>
|
||||
At this point, you have nothing but a project directory.
|
||||
Run the <filename>bitbake</filename> command and see what
|
||||
it does:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake
|
||||
The BBPATH variable is not set and bitbake did not
|
||||
find a conf/bblayers.conf file in the expected location.
|
||||
Maybe you accidentally invoked bitbake from the wrong directory?
|
||||
DEBUG: Removed the following variables from the environment:
|
||||
GNOME_DESKTOP_SESSION_ID, XDG_CURRENT_DESKTOP,
|
||||
GNOME_KEYRING_CONTROL, DISPLAY, SSH_AGENT_PID, LANG, no_proxy,
|
||||
XDG_SESSION_PATH, XAUTHORITY, SESSION_MANAGER, SHLVL,
|
||||
MANDATORY_PATH, COMPIZ_CONFIG_PROFILE, WINDOWID, EDITOR,
|
||||
GPG_AGENT_INFO, SSH_AUTH_SOCK, GDMSESSION, GNOME_KEYRING_PID,
|
||||
XDG_SEAT_PATH, XDG_CONFIG_DIRS, LESSOPEN, DBUS_SESSION_BUS_ADDRESS,
|
||||
_, XDG_SESSION_COOKIE, DESKTOP_SESSION, LESSCLOSE, DEFAULTS_PATH,
|
||||
UBUNTU_MENUPROXY, OLDPWD, XDG_DATA_DIRS, COLORTERM, LS_COLORS
|
||||
</literallayout>
|
||||
The majority of this output is specific to environment variables
|
||||
that are not directly relevant to BitBake.
|
||||
However, the very first message regarding the
|
||||
<filename>BBPATH</filename> variable and the
|
||||
<filename>conf/bblayers.conf</filename> file
|
||||
is relevant.</para>
|
||||
<para>
|
||||
When you run BitBake, it begins looking for metadata files.
|
||||
The
|
||||
<link linkend='var-bb-BBPATH'><filename>BBPATH</filename></link>
|
||||
variable is what tells BitBake where to look for those files.
|
||||
<filename>BBPATH</filename> is not set and you need to set it.
|
||||
Without <filename>BBPATH</filename>, Bitbake cannot
|
||||
find any configuration files (<filename>.conf</filename>)
|
||||
or recipe files (<filename>.bb</filename>) at all.
|
||||
BitBake also cannot find the <filename>bitbake.conf</filename>
|
||||
file.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Setting <filename>BBPATH</filename>:</emphasis>
|
||||
For this example, you can set <filename>BBPATH</filename>
|
||||
in the same manner that you set <filename>PATH</filename>
|
||||
earlier in the appendix.
|
||||
You should realize, though, that it is much more flexible to set the
|
||||
<filename>BBPATH</filename> variable up in a configuration
|
||||
file for each project.</para>
|
||||
<para>From your shell, enter the following commands to set and
|
||||
export the <filename>BBPATH</filename> variable:
|
||||
<literallayout class='monospaced'>
|
||||
$ BBPATH="<replaceable>projectdirectory</replaceable>"
|
||||
$ export BBPATH
|
||||
</literallayout>
|
||||
Use your actual project directory in the command.
|
||||
BitBake uses that directory to find the metadata it needs for
|
||||
your project.
|
||||
<note>
|
||||
When specifying your project directory, do not use the
|
||||
tilde ("~") character as BitBake does not expand that character
|
||||
as the shell would.
|
||||
</note>
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake:</emphasis>
|
||||
Now that you have <filename>BBPATH</filename> defined, run
|
||||
the <filename>bitbake</filename> command again:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake
|
||||
ERROR: Traceback (most recent call last):
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
|
||||
return func(fn, *args)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 173, in parse_config_file
|
||||
return bb.parse.handle(fn, data, include)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 99, in handle
|
||||
return h['handle'](fn, data, include)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 120, in handle
|
||||
abs_fn = resolve_file(fn, data)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/__init__.py", line 117, in resolve_file
|
||||
raise IOError("file %s not found in %s" % (fn, bbpath))
|
||||
IOError: file conf/bitbake.conf not found in /home/scott-lenovo/hello
|
||||
|
||||
ERROR: Unable to parse conf/bitbake.conf: file conf/bitbake.conf not found in /home/scott-lenovo/hello
|
||||
</literallayout>
|
||||
This sample output shows that BitBake could not find the
|
||||
<filename>conf/bitbake.conf</filename> file in the project
|
||||
directory.
|
||||
This file is the first thing BitBake must find in order
|
||||
to build a target.
|
||||
And, since the project directory for this example is
|
||||
empty, you need to provide a <filename>conf/bitbake.conf</filename>
|
||||
file.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Creating <filename>conf/bitbake.conf</filename>:</emphasis>
|
||||
The <filename>conf/bitbake.conf</filename> includes a number of
|
||||
configuration variables BitBake uses for metadata and recipe
|
||||
files.
|
||||
For this example, you need to create the file in your project directory
|
||||
and define some key BitBake variables.
|
||||
For more information on the <filename>bitbake.conf</filename> file,
|
||||
see
|
||||
<ulink url='http://git.openembedded.org/bitbake/tree/conf/bitbake.conf'></ulink>.
|
||||
</para>
|
||||
<para>Use the following commands to create the <filename>conf</filename>
|
||||
directory in the project directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ mkdir conf
|
||||
</literallayout>
|
||||
From within the <filename>conf</filename> directory, use
|
||||
some editor to create the <filename>bitbake.conf</filename>
|
||||
so that it contains the following:
|
||||
<literallayout class='monospaced'>
|
||||
<link linkend='var-bb-PN'>PN</link> = "${@bb.parse.BBHandler.vars_from_file(d.getVar('FILE', False),d)[0] or 'defaultpkgname'}"
|
||||
</literallayout>
|
||||
<literallayout class='monospaced'>
|
||||
TMPDIR = "${<link linkend='var-bb-TOPDIR'>TOPDIR</link>}/tmp"
|
||||
<link linkend='var-bb-CACHE'>CACHE</link> = "${TMPDIR}/cache"
|
||||
<link linkend='var-bb-STAMP'>STAMP</link> = "${TMPDIR}/${PN}/stamps"
|
||||
<link linkend='var-bb-T'>T</link> = "${TMPDIR}/${PN}/work"
|
||||
<link linkend='var-bb-B'>B</link> = "${TMPDIR}/${PN}"
|
||||
</literallayout>
|
||||
<note>
|
||||
Without a value for <filename>PN</filename>, the
|
||||
variables <filename>STAMP</filename>,
|
||||
<filename>T</filename>, and <filename>B</filename>,
|
||||
prevent more than one recipe from working. You can fix
|
||||
this by either setting <filename>PN</filename> to have
|
||||
a value similar to what OpenEmbedded and BitBake use
|
||||
in the default <filename>bitbake.conf</filename> file
|
||||
(see previous example). Or, by manually updating each
|
||||
recipe to set <filename>PN</filename>. You will also
|
||||
need to include <filename>PN</filename> as part of the
|
||||
<filename>STAMP</filename>, <filename>T</filename>, and
|
||||
<filename>B</filename> variable definitions in the
|
||||
<filename>local.conf</filename> file.
|
||||
</note>
|
||||
The <filename>TMPDIR</filename> variable establishes a directory
|
||||
that BitBake uses for build output and intermediate files other
|
||||
than the cached information used by the
|
||||
<link linkend='setscene'>Setscene</link> process.
|
||||
Here, the <filename>TMPDIR</filename> directory is set to
|
||||
<filename>hello/tmp</filename>.
|
||||
<note><title>Tip</title>
|
||||
You can always safely delete the <filename>tmp</filename>
|
||||
directory in order to rebuild a BitBake target.
|
||||
The build process creates the directory for you
|
||||
when you run BitBake.
|
||||
</note></para>
|
||||
<para>For information about each of the other variables defined in this
|
||||
example, click on the links to take you to the definitions in
|
||||
the glossary.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake:</emphasis>
|
||||
After making sure that the <filename>conf/bitbake.conf</filename>
|
||||
file exists, you can run the <filename>bitbake</filename>
|
||||
command again:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake
|
||||
ERROR: Traceback (most recent call last):
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 163, in wrapped
|
||||
return func(fn, *args)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/cookerdata.py", line 177, in _inherit
|
||||
bb.parse.BBHandler.inherit(bbclass, "configuration INHERITs", 0, data)
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/BBHandler.py", line 92, in inherit
|
||||
include(fn, file, lineno, d, "inherit")
|
||||
File "/home/scott-lenovo/bitbake/lib/bb/parse/parse_py/ConfHandler.py", line 100, in include
|
||||
raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), oldfn, lineno)
|
||||
ParseError: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
|
||||
|
||||
ERROR: Unable to parse base: ParseError in configuration INHERITs: Could not inherit file classes/base.bbclass
|
||||
</literallayout>
|
||||
In the sample output, BitBake could not find the
|
||||
<filename>classes/base.bbclass</filename> file.
|
||||
You need to create that file next.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Creating <filename>classes/base.bbclass</filename>:</emphasis>
|
||||
BitBake uses class files to provide common code and functionality.
|
||||
The minimally required class for BitBake is the
|
||||
<filename>classes/base.bbclass</filename> file.
|
||||
The <filename>base</filename> class is implicitly inherited by
|
||||
every recipe.
|
||||
BitBake looks for the class in the <filename>classes</filename>
|
||||
directory of the project (i.e <filename>hello/classes</filename>
|
||||
in this example).
|
||||
</para>
|
||||
<para>Create the <filename>classes</filename> directory as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd $HOME/hello
|
||||
$ mkdir classes
|
||||
</literallayout>
|
||||
Move to the <filename>classes</filename> directory and then
|
||||
create the <filename>base.bbclass</filename> file by inserting
|
||||
this single line:
|
||||
<literallayout class='monospaced'>
|
||||
addtask build
|
||||
</literallayout>
|
||||
The minimal task that BitBake runs is the
|
||||
<filename>do_build</filename> task.
|
||||
This is all the example needs in order to build the project.
|
||||
Of course, the <filename>base.bbclass</filename> can have much
|
||||
more depending on which build environments BitBake is
|
||||
supporting.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake:</emphasis>
|
||||
After making sure that the <filename>classes/base.bbclass</filename>
|
||||
file exists, you can run the <filename>bitbake</filename>
|
||||
command again:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake
|
||||
Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.
|
||||
</literallayout>
|
||||
BitBake is finally reporting no errors.
|
||||
However, you can see that it really does not have anything
|
||||
to do.
|
||||
You need to create a recipe that gives BitBake something to do.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Creating a Layer:</emphasis>
|
||||
While it is not really necessary for such a small example,
|
||||
it is good practice to create a layer in which to keep your
|
||||
code separate from the general metadata used by BitBake.
|
||||
Thus, this example creates and uses a layer called "mylayer".
|
||||
<note>
|
||||
You can find additional information on layers in the
|
||||
"<link linkend='layers'>Layers</link>" section.
|
||||
</note></para>
|
||||
|
||||
<para>Minimally, you need a recipe file and a layer configuration
|
||||
file in your layer.
|
||||
The configuration file needs to be in the <filename>conf</filename>
|
||||
directory inside the layer.
|
||||
Use these commands to set up the layer and the <filename>conf</filename>
|
||||
directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd $HOME
|
||||
$ mkdir mylayer
|
||||
$ cd mylayer
|
||||
$ mkdir conf
|
||||
</literallayout>
|
||||
Move to the <filename>conf</filename> directory and create a
|
||||
<filename>layer.conf</filename> file that has the following:
|
||||
<literallayout class='monospaced'>
|
||||
BBPATH .= ":${<link linkend='var-bb-LAYERDIR'>LAYERDIR</link>}"
|
||||
|
||||
<link linkend='var-bb-BBFILES'>BBFILES</link> += "${LAYERDIR}/*.bb"
|
||||
|
||||
<link linkend='var-bb-BBFILE_COLLECTIONS'>BBFILE_COLLECTIONS</link> += "mylayer"
|
||||
<link linkend='var-bb-BBFILE_PATTERN'>BBFILE_PATTERN_mylayer</link> := "^${LAYERDIR_RE}/"
|
||||
</literallayout>
|
||||
For information on these variables, click the links
|
||||
to go to the definitions in the glossary.</para>
|
||||
<para>You need to create the recipe file next.
|
||||
Inside your layer at the top-level, use an editor and create
|
||||
a recipe file named <filename>printhello.bb</filename> that
|
||||
has the following:
|
||||
<literallayout class='monospaced'>
|
||||
<link linkend='var-bb-DESCRIPTION'>DESCRIPTION</link> = "Prints Hello World"
|
||||
<link linkend='var-bb-PN'>PN</link> = 'printhello'
|
||||
<link linkend='var-bb-PV'>PV</link> = '1'
|
||||
|
||||
python do_build() {
|
||||
bb.plain("********************");
|
||||
bb.plain("* *");
|
||||
bb.plain("* Hello, World! *");
|
||||
bb.plain("* *");
|
||||
bb.plain("********************");
|
||||
}
|
||||
</literallayout>
|
||||
The recipe file simply provides a description of the
|
||||
recipe, the name, version, and the <filename>do_build</filename>
|
||||
task, which prints out "Hello World" to the console.
|
||||
For more information on these variables, follow the links
|
||||
to the glossary.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake With a Target:</emphasis>
|
||||
Now that a BitBake target exists, run the command and provide
|
||||
that target:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd $HOME/hello
|
||||
$ bitbake printhello
|
||||
ERROR: no recipe files to build, check your BBPATH and BBFILES?
|
||||
|
||||
Summary: There was 1 ERROR message shown, returning a non-zero exit code.
|
||||
</literallayout>
|
||||
We have created the layer with the recipe and the layer
|
||||
configuration file but it still seems that BitBake cannot
|
||||
find the recipe.
|
||||
BitBake needs a <filename>conf/bblayers.conf</filename> that
|
||||
lists the layers for the project.
|
||||
Without this file, BitBake cannot find the recipe.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Creating <filename>conf/bblayers.conf</filename>:</emphasis>
|
||||
BitBake uses the <filename>conf/bblayers.conf</filename> file
|
||||
to locate layers needed for the project.
|
||||
This file must reside in the <filename>conf</filename> directory
|
||||
of the project (i.e. <filename>hello/conf</filename> for this
|
||||
example).</para>
|
||||
<para>Set your working directory to the <filename>hello/conf</filename>
|
||||
directory and then create the <filename>bblayers.conf</filename>
|
||||
file so that it contains the following:
|
||||
<literallayout class='monospaced'>
|
||||
BBLAYERS ?= " \
|
||||
/home/<you>/mylayer \
|
||||
"
|
||||
</literallayout>
|
||||
You need to provide your own information for
|
||||
<filename>you</filename> in the file.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Run Bitbake With a Target:</emphasis>
|
||||
Now that you have supplied the <filename>bblayers.conf</filename>
|
||||
file, run the <filename>bitbake</filename> command and provide
|
||||
the target:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake printhello
|
||||
Parsing recipes: 100% |##################################################################################|
|
||||
Time: 00:00:00
|
||||
Parsing of 1 .bb files complete (0 cached, 1 parsed). 1 targets, 0 skipped, 0 masked, 0 errors.
|
||||
NOTE: Resolving any missing task queue dependencies
|
||||
NOTE: Preparing RunQueue
|
||||
NOTE: Executing RunQueue Tasks
|
||||
********************
|
||||
* *
|
||||
* Hello, World! *
|
||||
* *
|
||||
********************
|
||||
NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
|
||||
</literallayout>
|
||||
BitBake finds the <filename>printhello</filename> recipe and
|
||||
successfully runs the task.
|
||||
<note>
|
||||
After the first execution, re-running
|
||||
<filename>bitbake printhello</filename> again will not
|
||||
result in a BitBake run that prints the same console
|
||||
output.
|
||||
The reason for this is that the first time the
|
||||
<filename>printhello.bb</filename> recipe's
|
||||
<filename>do_build</filename> task executes
|
||||
successfully, BitBake writes a stamp file for the task.
|
||||
Thus, the next time you attempt to run the task
|
||||
using that same <filename>bitbake</filename> command,
|
||||
BitBake notices the stamp and therefore determines
|
||||
that the task does not need to be re-run.
|
||||
If you delete the <filename>tmp</filename> directory
|
||||
or run <filename>bitbake -c clean printhello</filename>
|
||||
and then re-run the build, the "Hello, World!" message will
|
||||
be printed again.
|
||||
</note>
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</section>
|
||||
</appendix>
|
||||
@@ -1,653 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
========
|
||||
Overview
|
||||
========
|
||||
|
||||
|
|
||||
|
||||
Welcome to the BitBake User Manual. This manual provides information on
|
||||
the BitBake tool. The information attempts to be as independent as
|
||||
possible regarding systems that use BitBake, such as OpenEmbedded and
|
||||
the Yocto Project. In some cases, scenarios or examples within the
|
||||
context of a build system are used in the manual to help with
|
||||
understanding. For these cases, the manual clearly states the context.
|
||||
|
||||
.. _intro:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Fundamentally, BitBake is a generic task execution engine that allows
|
||||
shell and Python tasks to be run efficiently and in parallel while
|
||||
working within complex inter-task dependency constraints. One of
|
||||
BitBake's main users, OpenEmbedded, takes this core and builds embedded
|
||||
Linux software stacks using a task-oriented approach.
|
||||
|
||||
Conceptually, BitBake is similar to GNU Make in some regards but has
|
||||
significant differences:
|
||||
|
||||
- BitBake executes tasks according to the provided metadata that builds up
|
||||
the tasks. Metadata is stored in recipe (``.bb``) and related recipe
|
||||
"append" (``.bbappend``) files, configuration (``.conf``) and
|
||||
underlying include (``.inc``) files, and in class (``.bbclass``)
|
||||
files. The metadata provides BitBake with instructions on what tasks
|
||||
to run and the dependencies between those tasks.
|
||||
|
||||
- BitBake includes a fetcher library for obtaining source code from
|
||||
various places such as local files, source control systems, or
|
||||
websites.
|
||||
|
||||
- The instructions for each unit to be built (e.g. a piece of software)
|
||||
are known as "recipe" files and contain all the information about the
|
||||
unit (dependencies, source file locations, checksums, description and
|
||||
so on).
|
||||
|
||||
- BitBake includes a client/server abstraction and can be used from a
|
||||
command line or used as a service over XML-RPC and has several
|
||||
different user interfaces.
|
||||
|
||||
History and Goals
|
||||
=================
|
||||
|
||||
BitBake was originally a part of the OpenEmbedded project. It was
|
||||
inspired by the Portage package management system used by the Gentoo
|
||||
Linux distribution. On December 7, 2004, OpenEmbedded project team
|
||||
member Chris Larson split the project into two distinct pieces:
|
||||
|
||||
- BitBake, a generic task executor
|
||||
|
||||
- OpenEmbedded, a metadata set utilized by BitBake
|
||||
|
||||
Today, BitBake is the primary basis of the
|
||||
`OpenEmbedded <https://www.openembedded.org/>`__ project, which is being
|
||||
used to build and maintain Linux distributions such as the `Poky
|
||||
Reference Distribution <https://www.yoctoproject.org/software-item/poky/>`__,
|
||||
developed under the umbrella of the `Yocto Project <https://www.yoctoproject.org>`__.
|
||||
|
||||
Prior to BitBake, no other build tool adequately met the needs of an
|
||||
aspiring embedded Linux distribution. All of the build systems used by
|
||||
traditional desktop Linux distributions lacked important functionality,
|
||||
and none of the ad hoc Buildroot-based systems, prevalent in the
|
||||
embedded space, were scalable or maintainable.
|
||||
|
||||
Some important original goals for BitBake were:
|
||||
|
||||
- Handle cross-compilation.
|
||||
|
||||
- Handle inter-package dependencies (build time on target architecture,
|
||||
build time on native architecture, and runtime).
|
||||
|
||||
- Support running any number of tasks within a given package,
|
||||
including, but not limited to, fetching upstream sources, unpacking
|
||||
them, patching them, configuring them, and so forth.
|
||||
|
||||
- Be Linux distribution agnostic for both build and target systems.
|
||||
|
||||
- Be architecture agnostic.
|
||||
|
||||
- Support multiple build and target operating systems (e.g. Cygwin, the
|
||||
BSDs, and so forth).
|
||||
|
||||
- Be self-contained, rather than tightly integrated into the build
|
||||
machine's root filesystem.
|
||||
|
||||
- Handle conditional metadata on the target architecture, operating
|
||||
system, distribution, and machine.
|
||||
|
||||
- Be easy to use the tools to supply local metadata and packages
|
||||
against which to operate.
|
||||
|
||||
- Be easy to use BitBake to collaborate between multiple projects for
|
||||
their builds.
|
||||
|
||||
- Provide an inheritance mechanism to share common metadata between
|
||||
many packages.
|
||||
|
||||
Over time it became apparent that some further requirements were
|
||||
necessary:
|
||||
|
||||
- Handle variants of a base recipe (e.g. native, sdk, and multilib).
|
||||
|
||||
- Split metadata into layers and allow layers to enhance or override
|
||||
other layers.
|
||||
|
||||
- Allow representation of a given set of input variables to a task as a
|
||||
checksum. Based on that checksum, allow acceleration of builds with
|
||||
prebuilt components.
|
||||
|
||||
BitBake satisfies all the original requirements and many more with
|
||||
extensions being made to the basic functionality to reflect the
|
||||
additional requirements. Flexibility and power have always been the
|
||||
priorities. BitBake is highly extensible and supports embedded Python
|
||||
code and execution of any arbitrary tasks.
|
||||
|
||||
.. _Concepts:
|
||||
|
||||
Concepts
|
||||
========
|
||||
|
||||
BitBake is a program written in the Python language. At the highest
|
||||
level, BitBake interprets metadata, decides what tasks are required to
|
||||
run, and executes those tasks. Similar to GNU Make, BitBake controls how
|
||||
software is built. GNU Make achieves its control through "makefiles",
|
||||
while BitBake uses "recipes".
|
||||
|
||||
BitBake extends the capabilities of a simple tool like GNU Make by
|
||||
allowing for the definition of much more complex tasks, such as
|
||||
assembling entire embedded Linux distributions.
|
||||
|
||||
The remainder of this section introduces several concepts that should be
|
||||
understood in order to better leverage the power of BitBake.
|
||||
|
||||
Recipes
|
||||
-------
|
||||
|
||||
BitBake Recipes, which are denoted by the file extension ``.bb``, are
|
||||
the most basic metadata files. These recipe files provide BitBake with
|
||||
the following:
|
||||
|
||||
- Descriptive information about the package (author, homepage, license,
|
||||
and so on)
|
||||
|
||||
- The version of the recipe
|
||||
|
||||
- Existing dependencies (both build and runtime dependencies)
|
||||
|
||||
- Where the source code resides and how to fetch it
|
||||
|
||||
- Whether the source code requires any patches, where to find them, and
|
||||
how to apply them
|
||||
|
||||
- How to configure and compile the source code
|
||||
|
||||
- How to assemble the generated artifacts into one or more installable
|
||||
packages
|
||||
|
||||
- Where on the target machine to install the package or packages
|
||||
created
|
||||
|
||||
Within the context of BitBake, or any project utilizing BitBake as its
|
||||
build system, files with the ``.bb`` extension are referred to as
|
||||
recipes.
|
||||
|
||||
.. note::
|
||||
|
||||
The term "package" is also commonly used to describe recipes.
|
||||
However, since the same word is used to describe packaged output from
|
||||
a project, it is best to maintain a single descriptive term -
|
||||
"recipes". Put another way, a single "recipe" file is quite capable
|
||||
of generating a number of related but separately installable
|
||||
"packages". In fact, that ability is fairly common.
|
||||
|
||||
Configuration Files
|
||||
-------------------
|
||||
|
||||
Configuration files, which are denoted by the ``.conf`` extension,
|
||||
define various configuration variables that govern the project's build
|
||||
process. These files fall into several areas that define machine
|
||||
configuration, distribution configuration, possible compiler tuning,
|
||||
general common configuration, and user configuration. The main
|
||||
configuration file is the sample ``bitbake.conf`` file, which is located
|
||||
within the BitBake source tree ``conf`` directory.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
Class files, which are denoted by the ``.bbclass`` extension, contain
|
||||
information that is useful to share between metadata files. The BitBake
|
||||
source tree currently comes with one class metadata file called
|
||||
``base.bbclass``. You can find this file in the ``classes`` directory.
|
||||
The ``base.bbclass`` class files is special since it is always included
|
||||
automatically for all recipes and classes. This class contains
|
||||
definitions for standard basic tasks such as fetching, unpacking,
|
||||
configuring (empty by default), compiling (runs any Makefile present),
|
||||
installing (empty by default) and packaging (empty by default). These
|
||||
tasks are often overridden or extended by other classes added during the
|
||||
project development process.
|
||||
|
||||
Layers
|
||||
------
|
||||
|
||||
Layers allow you to isolate different types of customizations from each
|
||||
other. While you might find it tempting to keep everything in one layer
|
||||
when working on a single project, the more modular your metadata, the
|
||||
easier it is to cope with future changes.
|
||||
|
||||
To illustrate how you can use layers to keep things modular, consider
|
||||
customizations you might make to support a specific target machine.
|
||||
These types of customizations typically reside in a special layer,
|
||||
rather than a general layer, called a Board Support Package (BSP) layer.
|
||||
Furthermore, the machine customizations should be isolated from recipes
|
||||
and metadata that support a new GUI environment, for example. This
|
||||
situation gives you a couple of layers: one for the machine
|
||||
configurations and one for the GUI environment. It is important to
|
||||
understand, however, that the BSP layer can still make machine-specific
|
||||
additions to recipes within the GUI environment layer without polluting
|
||||
the GUI layer itself with those machine-specific changes. You can
|
||||
accomplish this through a recipe that is a BitBake append
|
||||
(``.bbappend``) file.
|
||||
|
||||
.. _append-bbappend-files:
|
||||
|
||||
Append Files
|
||||
------------
|
||||
|
||||
Append files, which are files that have the ``.bbappend`` file
|
||||
extension, extend or override information in an existing recipe file.
|
||||
|
||||
BitBake expects every append file to have a corresponding recipe file.
|
||||
Furthermore, the append file and corresponding recipe file must use the
|
||||
same root filename. The filenames can differ only in the file type
|
||||
suffix used (e.g. ``formfactor_0.0.bb`` and
|
||||
``formfactor_0.0.bbappend``).
|
||||
|
||||
Information in append files extends or overrides the information in the
|
||||
underlying, similarly-named recipe files.
|
||||
|
||||
When you name an append file, you can use the "``%``" wildcard character
|
||||
to allow for matching recipe names. For example, suppose you have an
|
||||
append file named as follows::
|
||||
|
||||
busybox_1.21.%.bbappend
|
||||
|
||||
That append file
|
||||
would match any ``busybox_1.21.``\ x\ ``.bb`` version of the recipe. So,
|
||||
the append file would match the following recipe names::
|
||||
|
||||
busybox_1.21.1.bb
|
||||
busybox_1.21.2.bb
|
||||
busybox_1.21.3.bb
|
||||
|
||||
.. note::
|
||||
|
||||
The use of the " % " character is limited in that it only works directly in
|
||||
front of the .bbappend portion of the append file's name. You cannot use the
|
||||
wildcard character in any other location of the name.
|
||||
|
||||
If the ``busybox`` recipe was updated to ``busybox_1.3.0.bb``, the
|
||||
append name would not match. However, if you named the append file
|
||||
``busybox_1.%.bbappend``, then you would have a match.
|
||||
|
||||
In the most general case, you could name the append file something as
|
||||
simple as ``busybox_%.bbappend`` to be entirely version independent.
|
||||
|
||||
Obtaining BitBake
|
||||
=================
|
||||
|
||||
You can obtain BitBake several different ways:
|
||||
|
||||
- **Cloning BitBake:** Using Git to clone the BitBake source code
|
||||
repository is the recommended method for obtaining BitBake. Cloning
|
||||
the repository makes it easy to get bug fixes and have access to
|
||||
stable branches and the master branch. Once you have cloned BitBake,
|
||||
you should use the latest stable branch for development since the
|
||||
master branch is for BitBake development and might contain less
|
||||
stable changes.
|
||||
|
||||
You usually need a version of BitBake that matches the metadata you
|
||||
are using. The metadata is generally backwards compatible but not
|
||||
forward compatible.
|
||||
|
||||
Here is an example that clones the BitBake repository::
|
||||
|
||||
$ git clone git://git.openembedded.org/bitbake
|
||||
|
||||
This command clones the BitBake
|
||||
Git repository into a directory called ``bitbake``. Alternatively,
|
||||
you can designate a directory after the ``git clone`` command if you
|
||||
want to call the new directory something other than ``bitbake``. Here
|
||||
is an example that names the directory ``bbdev``::
|
||||
|
||||
$ git clone git://git.openembedded.org/bitbake bbdev
|
||||
|
||||
- **Installation using your Distribution Package Management System:**
|
||||
This method is not recommended because the BitBake version that is
|
||||
provided by your distribution, in most cases, is several releases
|
||||
behind a snapshot of the BitBake repository.
|
||||
|
||||
- **Taking a snapshot of BitBake:** Downloading a snapshot of BitBake
|
||||
from the source code repository gives you access to a known branch or
|
||||
release of BitBake.
|
||||
|
||||
.. note::
|
||||
|
||||
Cloning the Git repository, as described earlier, is the preferred
|
||||
method for getting BitBake. Cloning the repository makes it easier
|
||||
to update as patches are added to the stable branches.
|
||||
|
||||
The following example downloads a snapshot of BitBake version 1.17.0::
|
||||
|
||||
$ wget https://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
|
||||
$ tar zxpvf bitbake-1.17.0.tar.gz
|
||||
|
||||
After extraction of the tarball using
|
||||
the tar utility, you have a directory entitled ``bitbake-1.17.0``.
|
||||
|
||||
- **Using the BitBake that Comes With Your Build Checkout:** A final
|
||||
possibility for getting a copy of BitBake is that it already comes
|
||||
with your checkout of a larger BitBake-based build system, such as
|
||||
Poky. Rather than manually checking out individual layers and gluing
|
||||
them together yourself, you can check out an entire build system. The
|
||||
checkout will already include a version of BitBake that has been
|
||||
thoroughly tested for compatibility with the other components. For
|
||||
information on how to check out a particular BitBake-based build
|
||||
system, consult that build system's supporting documentation.
|
||||
|
||||
.. _bitbake-user-manual-command:
|
||||
|
||||
The BitBake Command
|
||||
===================
|
||||
|
||||
The ``bitbake`` command is the primary interface to the BitBake tool.
|
||||
This section presents the BitBake command syntax and provides several
|
||||
execution examples.
|
||||
|
||||
Usage and syntax
|
||||
----------------
|
||||
|
||||
Following is the usage and syntax for BitBake::
|
||||
|
||||
$ bitbake -h
|
||||
Usage: bitbake [options] [recipename/target recipe:do_task ...]
|
||||
|
||||
Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
|
||||
It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
|
||||
will provide the layer, BBFILES and other configuration information.
|
||||
|
||||
Options:
|
||||
--version show program's version number and exit
|
||||
-h, --help show this help message and exit
|
||||
-b BUILDFILE, --buildfile=BUILDFILE
|
||||
Execute tasks from a specific .bb recipe directly.
|
||||
WARNING: Does not handle any dependencies from other
|
||||
recipes.
|
||||
-k, --continue Continue as much as possible after an error. While the
|
||||
target that failed and anything depending on it cannot
|
||||
be built, as much as possible will be built before
|
||||
stopping.
|
||||
-f, --force Force the specified targets/task to run (invalidating
|
||||
any existing stamp file).
|
||||
-c CMD, --cmd=CMD Specify the task to execute. The exact options
|
||||
available depend on the metadata. Some examples might
|
||||
be 'compile' or 'populate_sysroot' or 'listtasks' may
|
||||
give a list of the tasks available.
|
||||
-C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
|
||||
Invalidate the stamp for the specified task such as
|
||||
'compile' and then run the default task for the
|
||||
specified target(s).
|
||||
-r PREFILE, --read=PREFILE
|
||||
Read the specified file before bitbake.conf.
|
||||
-R POSTFILE, --postread=POSTFILE
|
||||
Read the specified file after bitbake.conf.
|
||||
-v, --verbose Enable tracing of shell tasks (with 'set -x'). Also
|
||||
print bb.note(...) messages to stdout (in addition to
|
||||
writing them to ${T}/log.do_<task>).
|
||||
-D, --debug Increase the debug level. You can specify this more
|
||||
than once. -D sets the debug level to 1, where only
|
||||
bb.debug(1, ...) messages are printed to stdout; -DD
|
||||
sets the debug level to 2, where both bb.debug(1, ...)
|
||||
and bb.debug(2, ...) messages are printed; etc.
|
||||
Without -D, no debug messages are printed. Note that
|
||||
-D only affects output to stdout. All debug messages
|
||||
are written to ${T}/log.do_taskname, regardless of the
|
||||
debug level.
|
||||
-q, --quiet Output less log message data to the terminal. You can
|
||||
specify this more than once.
|
||||
-n, --dry-run Don't execute, just go through the motions.
|
||||
-S SIGNATURE_HANDLER, --dump-signatures=SIGNATURE_HANDLER
|
||||
Dump out the signature construction information, with
|
||||
no task execution. The SIGNATURE_HANDLER parameter is
|
||||
passed to the handler. Two common values are none and
|
||||
printdiff but the handler may define more/less. none
|
||||
means only dump the signature, printdiff means compare
|
||||
the dumped signature with the cached one.
|
||||
-p, --parse-only Quit after parsing the BB recipes.
|
||||
-s, --show-versions Show current and preferred versions of all recipes.
|
||||
-e, --environment Show the global or per-recipe environment complete
|
||||
with information about where variables were
|
||||
set/changed.
|
||||
-g, --graphviz Save dependency tree information for the specified
|
||||
targets in the dot syntax.
|
||||
-I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
|
||||
Assume these dependencies don't exist and are already
|
||||
provided (equivalent to ASSUME_PROVIDED). Useful to
|
||||
make dependency graphs more appealing
|
||||
-l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
|
||||
Show debug logging for the specified logging domains
|
||||
-P, --profile Profile the command and save reports.
|
||||
-u UI, --ui=UI The user interface to use (knotty, ncurses, taskexp or
|
||||
teamcity - default knotty).
|
||||
--token=XMLRPCTOKEN Specify the connection token to be used when
|
||||
connecting to a remote server.
|
||||
--revisions-changed Set the exit code depending on whether upstream
|
||||
floating revisions have changed or not.
|
||||
--server-only Run bitbake without a UI, only starting a server
|
||||
(cooker) process.
|
||||
-B BIND, --bind=BIND The name/address for the bitbake xmlrpc server to bind
|
||||
to.
|
||||
-T SERVER_TIMEOUT, --idle-timeout=SERVER_TIMEOUT
|
||||
Set timeout to unload bitbake server due to
|
||||
inactivity, set to -1 means no unload, default:
|
||||
Environment variable BB_SERVER_TIMEOUT.
|
||||
--no-setscene Do not run any setscene tasks. sstate will be ignored
|
||||
and everything needed, built.
|
||||
--skip-setscene Skip setscene tasks if they would be executed. Tasks
|
||||
previously restored from sstate will be kept, unlike
|
||||
--no-setscene
|
||||
--setscene-only Only run setscene tasks, don't run any real tasks.
|
||||
--remote-server=REMOTE_SERVER
|
||||
Connect to the specified server.
|
||||
-m, --kill-server Terminate any running bitbake server.
|
||||
--observe-only Connect to a server as an observing-only client.
|
||||
--status-only Check the status of the remote bitbake server.
|
||||
-w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
|
||||
Writes the event log of the build to a bitbake event
|
||||
json file. Use '' (empty string) to assign the name
|
||||
automatically.
|
||||
--runall=RUNALL Run the specified task for any recipe in the taskgraph
|
||||
of the specified target (even if it wouldn't otherwise
|
||||
have run).
|
||||
--runonly=RUNONLY Run only the specified task within the taskgraph of
|
||||
the specified targets (and any task dependencies those
|
||||
tasks may have).
|
||||
|
||||
.. _bitbake-examples:
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
This section presents some examples showing how to use BitBake.
|
||||
|
||||
.. _example-executing-a-task-against-a-single-recipe:
|
||||
|
||||
Executing a Task Against a Single Recipe
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Executing tasks for a single recipe file is relatively simple. You
|
||||
specify the file in question, and BitBake parses it and executes the
|
||||
specified task. If you do not specify a task, BitBake executes the
|
||||
default task, which is "build". BitBake obeys inter-task dependencies
|
||||
when doing so.
|
||||
|
||||
The following command runs the build task, which is the default task, on
|
||||
the ``foo_1.0.bb`` recipe file::
|
||||
|
||||
$ bitbake -b foo_1.0.bb
|
||||
|
||||
The following command runs the clean task on the ``foo.bb`` recipe file::
|
||||
|
||||
$ bitbake -b foo.bb -c clean
|
||||
|
||||
.. note::
|
||||
|
||||
The "-b" option explicitly does not handle recipe dependencies. Other
|
||||
than for debugging purposes, it is instead recommended that you use
|
||||
the syntax presented in the next section.
|
||||
|
||||
Executing Tasks Against a Set of Recipe Files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are a number of additional complexities introduced when one wants
|
||||
to manage multiple ``.bb`` files. Clearly there needs to be a way to
|
||||
tell BitBake what files are available and, of those, which you want to
|
||||
execute. There also needs to be a way for each recipe to express its
|
||||
dependencies, both for build-time and runtime. There must be a way for
|
||||
you to express recipe preferences when multiple recipes provide the same
|
||||
functionality, or when there are multiple versions of a recipe.
|
||||
|
||||
The ``bitbake`` command, when not using "--buildfile" or "-b" only
|
||||
accepts a "PROVIDES". You cannot provide anything else. By default, a
|
||||
recipe file generally "PROVIDES" its "packagename" as shown in the
|
||||
following example::
|
||||
|
||||
$ bitbake foo
|
||||
|
||||
This next example "PROVIDES" the
|
||||
package name and also uses the "-c" option to tell BitBake to just
|
||||
execute the ``do_clean`` task::
|
||||
|
||||
$ bitbake -c clean foo
|
||||
|
||||
Executing a List of Task and Recipe Combinations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The BitBake command line supports specifying different tasks for
|
||||
individual targets when you specify multiple targets. For example,
|
||||
suppose you had two targets (or recipes) ``myfirstrecipe`` and
|
||||
``mysecondrecipe`` and you needed BitBake to run ``taskA`` for the first
|
||||
recipe and ``taskB`` for the second recipe::
|
||||
|
||||
$ bitbake myfirstrecipe:do_taskA mysecondrecipe:do_taskB
|
||||
|
||||
Generating Dependency Graphs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
BitBake is able to generate dependency graphs using the ``dot`` syntax.
|
||||
You can convert these graphs into images using the ``dot`` tool from
|
||||
`Graphviz <http://www.graphviz.org>`__.
|
||||
|
||||
When you generate a dependency graph, BitBake writes two files to the
|
||||
current working directory:
|
||||
|
||||
- ``task-depends.dot``: Shows dependencies between tasks. These
|
||||
dependencies match BitBake's internal task execution list.
|
||||
|
||||
- ``pn-buildlist``: Shows a simple list of targets that are to be
|
||||
built.
|
||||
|
||||
To stop depending on common depends, use the ``-I`` depend option and
|
||||
BitBake omits them from the graph. Leaving this information out can
|
||||
produce more readable graphs. This way, you can remove from the graph
|
||||
:term:`DEPENDS` from inherited classes such as ``base.bbclass``.
|
||||
|
||||
Here are two examples that create dependency graphs. The second example
|
||||
omits depends common in OpenEmbedded from the graph::
|
||||
|
||||
$ bitbake -g foo
|
||||
|
||||
$ bitbake -g -I virtual/kernel -I eglibc foo
|
||||
|
||||
Executing a Multiple Configuration Build
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
BitBake is able to build multiple images or packages using a single
|
||||
command where the different targets require different configurations
|
||||
(multiple configuration builds). Each target, in this scenario, is
|
||||
referred to as a "multiconfig".
|
||||
|
||||
To accomplish a multiple configuration build, you must define each
|
||||
target's configuration separately using a parallel configuration file in
|
||||
the build directory. The location for these multiconfig configuration
|
||||
files is specific. They must reside in the current build directory in a
|
||||
sub-directory of ``conf`` named ``multiconfig``. Following is an example
|
||||
for two separate targets:
|
||||
|
||||
.. image:: figures/bb_multiconfig_files.png
|
||||
:align: center
|
||||
|
||||
The reason for this required file hierarchy is because the :term:`BBPATH`
|
||||
variable is not constructed until the layers are parsed. Consequently,
|
||||
using the configuration file as a pre-configuration file is not possible
|
||||
unless it is located in the current working directory.
|
||||
|
||||
Minimally, each configuration file must define the machine and the
|
||||
temporary directory BitBake uses for the build. Suggested practice
|
||||
dictates that you do not overlap the temporary directories used during
|
||||
the builds.
|
||||
|
||||
Aside from separate configuration files for each target, you must also
|
||||
enable BitBake to perform multiple configuration builds. Enabling is
|
||||
accomplished by setting the
|
||||
:term:`BBMULTICONFIG` variable in the
|
||||
``local.conf`` configuration file. As an example, suppose you had
|
||||
configuration files for ``target1`` and ``target2`` defined in the build
|
||||
directory. The following statement in the ``local.conf`` file both
|
||||
enables BitBake to perform multiple configuration builds and specifies
|
||||
the two extra multiconfigs::
|
||||
|
||||
BBMULTICONFIG = "target1 target2"
|
||||
|
||||
Once the target configuration files are in place and BitBake has been
|
||||
enabled to perform multiple configuration builds, use the following
|
||||
command form to start the builds::
|
||||
|
||||
$ bitbake [mc:multiconfigname:]target [[[mc:multiconfigname:]target] ... ]
|
||||
|
||||
Here is an example for two extra multiconfigs: ``target1`` and ``target2``::
|
||||
|
||||
$ bitbake mc::target mc:target1:target mc:target2:target
|
||||
|
||||
.. _bb-enabling-multiple-configuration-build-dependencies:
|
||||
|
||||
Enabling Multiple Configuration Build Dependencies
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sometimes dependencies can exist between targets (multiconfigs) in a
|
||||
multiple configuration build. For example, suppose that in order to
|
||||
build an image for a particular architecture, the root filesystem of
|
||||
another build for a different architecture needs to exist. In other
|
||||
words, the image for the first multiconfig depends on the root
|
||||
filesystem of the second multiconfig. This dependency is essentially
|
||||
that the task in the recipe that builds one multiconfig is dependent on
|
||||
the completion of the task in the recipe that builds another
|
||||
multiconfig.
|
||||
|
||||
To enable dependencies in a multiple configuration build, you must
|
||||
declare the dependencies in the recipe using the following statement
|
||||
form::
|
||||
|
||||
task_or_package[mcdepends] = "mc:from_multiconfig:to_multiconfig:recipe_name:task_on_which_to_depend"
|
||||
|
||||
To better show how to use this statement, consider an example with two
|
||||
multiconfigs: ``target1`` and ``target2``::
|
||||
|
||||
image_task[mcdepends] = "mc:target1:target2:image2:rootfs_task"
|
||||
|
||||
In this example, the
|
||||
``from_multiconfig`` is "target1" and the ``to_multiconfig`` is "target2". The
|
||||
task on which the image whose recipe contains image_task depends on the
|
||||
completion of the rootfs_task used to build out image2, which is
|
||||
associated with the "target2" multiconfig.
|
||||
|
||||
Once you set up this dependency, you can build the "target1" multiconfig
|
||||
using a BitBake command as follows::
|
||||
|
||||
$ bitbake mc:target1:image1
|
||||
|
||||
This command executes all the tasks needed to create ``image1`` for the "target1"
|
||||
multiconfig. Because of the dependency, BitBake also executes through
|
||||
the ``rootfs_task`` for the "target2" multiconfig build.
|
||||
|
||||
Having a recipe depend on the root filesystem of another build might not
|
||||
seem that useful. Consider this change to the statement in the image1
|
||||
recipe::
|
||||
|
||||
image_task[mcdepends] = "mc:target1:target2:image2:image_task"
|
||||
|
||||
In this case, BitBake must create ``image2`` for the "target2" build since
|
||||
the "target1" build depends on it.
|
||||
|
||||
Because "target1" and "target2" are enabled for multiple configuration
|
||||
builds and have separate configuration files, BitBake places the
|
||||
artifacts for each build in the respective temporary build directories.
|
||||
894
bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
Normal file
894
bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
Normal file
@@ -0,0 +1,894 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<chapter id="bitbake-user-manual-intro">
|
||||
<title>Overview</title>
|
||||
|
||||
<para>
|
||||
Welcome to the BitBake User Manual.
|
||||
This manual provides information on the BitBake tool.
|
||||
The information attempts to be as independent as possible regarding
|
||||
systems that use BitBake, such as OpenEmbedded and the
|
||||
Yocto Project.
|
||||
In some cases, scenarios or examples within the context of
|
||||
a build system are used in the manual to help with understanding.
|
||||
For these cases, the manual clearly states the context.
|
||||
</para>
|
||||
|
||||
<section id="intro">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
Fundamentally, BitBake is a generic task execution
|
||||
engine that allows shell and Python tasks to be run
|
||||
efficiently and in parallel while working within
|
||||
complex inter-task dependency constraints.
|
||||
One of BitBake's main users, OpenEmbedded, takes this core
|
||||
and builds embedded Linux software stacks using
|
||||
a task-oriented approach.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Conceptually, BitBake is similar to GNU Make in
|
||||
some regards but has significant differences:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
BitBake executes tasks according to provided
|
||||
metadata that builds up the tasks.
|
||||
Metadata is stored in recipe (<filename>.bb</filename>)
|
||||
and related recipe "append" (<filename>.bbappend</filename>)
|
||||
files, configuration (<filename>.conf</filename>) and
|
||||
underlying include (<filename>.inc</filename>) files, and
|
||||
in class (<filename>.bbclass</filename>) files.
|
||||
The metadata provides
|
||||
BitBake with instructions on what tasks to run and
|
||||
the dependencies between those tasks.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
BitBake includes a fetcher library for obtaining source
|
||||
code from various places such as local files, source control
|
||||
systems, or websites.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
The instructions for each unit to be built (e.g. a piece
|
||||
of software) are known as "recipe" files and
|
||||
contain all the information about the unit
|
||||
(dependencies, source file locations, checksums, description
|
||||
and so on).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
BitBake includes a client/server abstraction and can
|
||||
be used from a command line or used as a service over
|
||||
XML-RPC and has several different user interfaces.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="history-and-goals">
|
||||
<title>History and Goals</title>
|
||||
|
||||
<para>
|
||||
BitBake was originally a part of the OpenEmbedded project.
|
||||
It was inspired by the Portage package management system
|
||||
used by the Gentoo Linux distribution.
|
||||
On December 7, 2004, OpenEmbedded project team member
|
||||
Chris Larson split the project into two distinct pieces:
|
||||
<itemizedlist>
|
||||
<listitem><para>BitBake, a generic task executor</para></listitem>
|
||||
<listitem><para>OpenEmbedded, a metadata set utilized by
|
||||
BitBake</para></listitem>
|
||||
</itemizedlist>
|
||||
Today, BitBake is the primary basis of the
|
||||
<ulink url="http://www.openembedded.org/">OpenEmbedded</ulink>
|
||||
project, which is being used to build and maintain Linux
|
||||
distributions such as the
|
||||
<ulink url='http://www.angstrom-distribution.org/'>Angstrom Distribution</ulink>,
|
||||
and which is also being used as the build tool for Linux projects
|
||||
such as the
|
||||
<ulink url='http://www.yoctoproject.org'>Yocto Project</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Prior to BitBake, no other build tool adequately met the needs of
|
||||
an aspiring embedded Linux distribution.
|
||||
All of the build systems used by traditional desktop Linux
|
||||
distributions lacked important functionality, and none of the
|
||||
ad hoc Buildroot-based systems, prevalent in the
|
||||
embedded space, were scalable or maintainable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some important original goals for BitBake were:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
Handle cross-compilation.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Handle inter-package dependencies (build time on
|
||||
target architecture, build time on native
|
||||
architecture, and runtime).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Support running any number of tasks within a given
|
||||
package, including, but not limited to, fetching
|
||||
upstream sources, unpacking them, patching them,
|
||||
configuring them, and so forth.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Be Linux distribution agnostic for both build and
|
||||
target systems.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Be architecture agnostic.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Support multiple build and target operating systems
|
||||
(e.g. Cygwin, the BSDs, and so forth).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Be self contained, rather than tightly
|
||||
integrated into the build machine's root
|
||||
filesystem.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Handle conditional metadata on the target architecture,
|
||||
operating system, distribution, and machine.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Be easy to use the tools to supply local metadata and packages
|
||||
against which to operate.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Be easy to use BitBake to collaborate between multiple
|
||||
projects for their builds.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Provide an inheritance mechanism to share
|
||||
common metadata between many packages.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
Over time it became apparent that some further requirements
|
||||
were necessary:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
Handle variants of a base recipe (e.g. native, sdk,
|
||||
and multilib).
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Split metadata into layers and allow layers
|
||||
to enhance or override other layers.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Allow representation of a given set of input variables
|
||||
to a task as a checksum.
|
||||
Based on that checksum, allow acceleration of builds
|
||||
with prebuilt components.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
BitBake satisfies all the original requirements and many more
|
||||
with extensions being made to the basic functionality to
|
||||
reflect the additional requirements.
|
||||
Flexibility and power have always been the priorities.
|
||||
BitBake is highly extensible and supports embedded Python code and
|
||||
execution of any arbitrary tasks.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="Concepts">
|
||||
<title>Concepts</title>
|
||||
|
||||
<para>
|
||||
BitBake is a program written in the Python language.
|
||||
At the highest level, BitBake interprets metadata, decides
|
||||
what tasks are required to run, and executes those tasks.
|
||||
Similar to GNU Make, BitBake controls how software is
|
||||
built.
|
||||
GNU Make achieves its control through "makefiles", while
|
||||
BitBake uses "recipes".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake extends the capabilities of a simple
|
||||
tool like GNU Make by allowing for the definition of much more
|
||||
complex tasks, such as assembling entire embedded Linux
|
||||
distributions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The remainder of this section introduces several concepts
|
||||
that should be understood in order to better leverage
|
||||
the power of BitBake.
|
||||
</para>
|
||||
|
||||
<section id='recipes'>
|
||||
<title>Recipes</title>
|
||||
|
||||
<para>
|
||||
BitBake Recipes, which are denoted by the file extension
|
||||
<filename>.bb</filename>, are the most basic metadata files.
|
||||
These recipe files provide BitBake with the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>Descriptive information about the
|
||||
package (author, homepage, license, and so on)</para></listitem>
|
||||
<listitem><para>The version of the recipe</para></listitem>
|
||||
<listitem><para>Existing dependencies (both build
|
||||
and runtime dependencies)</para></listitem>
|
||||
<listitem><para>Where the source code resides and
|
||||
how to fetch it</para></listitem>
|
||||
<listitem><para>Whether the source code requires
|
||||
any patches, where to find them, and how to apply
|
||||
them</para></listitem>
|
||||
<listitem><para>How to configure and compile the
|
||||
source code</para></listitem>
|
||||
<listitem><para>Where on the target machine to install the
|
||||
package or packages created</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Within the context of BitBake, or any project utilizing BitBake
|
||||
as its build system, files with the <filename>.bb</filename>
|
||||
extension are referred to as recipes.
|
||||
<note>
|
||||
The term "package" is also commonly used to describe recipes.
|
||||
However, since the same word is used to describe packaged
|
||||
output from a project, it is best to maintain a single
|
||||
descriptive term - "recipes".
|
||||
Put another way, a single "recipe" file is quite capable
|
||||
of generating a number of related but separately installable
|
||||
"packages".
|
||||
In fact, that ability is fairly common.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='configuration-files'>
|
||||
<title>Configuration Files</title>
|
||||
|
||||
<para>
|
||||
Configuration files, which are denoted by the
|
||||
<filename>.conf</filename> extension, define
|
||||
various configuration variables that govern the project's build
|
||||
process.
|
||||
These files fall into several areas that define
|
||||
machine configuration options, distribution configuration
|
||||
options, compiler tuning options, general common
|
||||
configuration options, and user configuration options.
|
||||
The main configuration file is the sample
|
||||
<filename>bitbake.conf</filename> file, which is
|
||||
located within the BitBake source tree
|
||||
<filename>conf</filename> directory.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='classes'>
|
||||
<title>Classes</title>
|
||||
|
||||
<para>
|
||||
Class files, which are denoted by the
|
||||
<filename>.bbclass</filename> extension, contain
|
||||
information that is useful to share between metadata files.
|
||||
The BitBake source tree currently comes with one class metadata file
|
||||
called <filename>base.bbclass</filename>.
|
||||
You can find this file in the
|
||||
<filename>classes</filename> directory.
|
||||
The <filename>base.bbclass</filename> class files is special since it
|
||||
is always included automatically for all recipes
|
||||
and classes.
|
||||
This class contains definitions for standard basic tasks such
|
||||
as fetching, unpacking, configuring (empty by default),
|
||||
compiling (runs any Makefile present), installing (empty by
|
||||
default) and packaging (empty by default).
|
||||
These tasks are often overridden or extended by other classes
|
||||
added during the project development process.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='layers'>
|
||||
<title>Layers</title>
|
||||
|
||||
<para>
|
||||
Layers allow you to isolate different types of
|
||||
customizations from each other.
|
||||
While you might find it tempting to keep everything in one layer
|
||||
when working on a single project, the more modular you organize
|
||||
your metadata, the easier it is to cope with future changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To illustrate how you can use layers to keep things modular,
|
||||
consider customizations you might make to support a specific target machine.
|
||||
These types of customizations typically reside in a special layer,
|
||||
rather than a general layer, called a Board Support Package (BSP)
|
||||
Layer.
|
||||
Furthermore, the machine customizations should be isolated from
|
||||
recipes and metadata that support a new GUI environment, for
|
||||
example.
|
||||
This situation gives you a couple of layers: one for the machine
|
||||
configurations and one for the GUI environment.
|
||||
It is important to understand, however, that the BSP layer can still
|
||||
make machine-specific additions to recipes within
|
||||
the GUI environment layer without polluting the GUI layer itself
|
||||
with those machine-specific changes.
|
||||
You can accomplish this through a recipe that is a BitBake append
|
||||
(<filename>.bbappend</filename>) file.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='append-bbappend-files'>
|
||||
<title>Append Files</title>
|
||||
|
||||
<para>
|
||||
Append files, which are files that have the
|
||||
<filename>.bbappend</filename> file extension, extend or
|
||||
override information in an existing recipe file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BitBake expects every append file to have a corresponding recipe file.
|
||||
Furthermore, the append file and corresponding recipe file
|
||||
must use the same root filename.
|
||||
The filenames can differ only in the file type suffix used
|
||||
(e.g. <filename>formfactor_0.0.bb</filename> and
|
||||
<filename>formfactor_0.0.bbappend</filename>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Information in append files extends or
|
||||
overrides the information in the underlying,
|
||||
similarly-named recipe files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you name an append file, you can use the
|
||||
"<filename>%</filename>" wildcard character to allow for matching
|
||||
recipe names.
|
||||
For example, suppose you have an append file named
|
||||
as follows:
|
||||
<literallayout class='monospaced'>
|
||||
busybox_1.21.%.bbappend
|
||||
</literallayout>
|
||||
That append file would match any <filename>busybox_1.21.</filename><replaceable>x</replaceable><filename>.bb</filename>
|
||||
version of the recipe.
|
||||
So, the append file would match the following recipe names:
|
||||
<literallayout class='monospaced'>
|
||||
busybox_1.21.1.bb
|
||||
busybox_1.21.2.bb
|
||||
busybox_1.21.3.bb
|
||||
</literallayout>
|
||||
<note><title>Important</title>
|
||||
The use of the "<filename>%</filename>" character
|
||||
is limited in that it only works directly in front of the
|
||||
<filename>.bbappend</filename> portion of the append file's
|
||||
name.
|
||||
You cannot use the wildcard character in any other
|
||||
location of the name.
|
||||
</note>
|
||||
If the <filename>busybox</filename> recipe was updated to
|
||||
<filename>busybox_1.3.0.bb</filename>, the append name would not
|
||||
match.
|
||||
However, if you named the append file
|
||||
<filename>busybox_1.%.bbappend</filename>, then you would have a match.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the most general case, you could name the append file something as
|
||||
simple as <filename>busybox_%.bbappend</filename> to be entirely
|
||||
version independent.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='obtaining-bitbake'>
|
||||
<title>Obtaining BitBake</title>
|
||||
|
||||
<para>
|
||||
You can obtain BitBake several different ways:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Cloning BitBake:</emphasis>
|
||||
Using Git to clone the BitBake source code repository
|
||||
is the recommended method for obtaining BitBake.
|
||||
Cloning the repository makes it easy to get bug fixes
|
||||
and have access to stable branches and the master
|
||||
branch.
|
||||
Once you have cloned BitBake, you should use
|
||||
the latest stable
|
||||
branch for development since the master branch is for
|
||||
BitBake development and might contain less stable changes.
|
||||
</para>
|
||||
<para>You usually need a version of BitBake
|
||||
that matches the metadata you are using.
|
||||
The metadata is generally backwards compatible but
|
||||
not forward compatible.</para>
|
||||
<para>Here is an example that clones the BitBake repository:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.openembedded.org/bitbake
|
||||
</literallayout>
|
||||
This command clones the BitBake Git repository into a
|
||||
directory called <filename>bitbake</filename>.
|
||||
Alternatively, you can
|
||||
designate a directory after the
|
||||
<filename>git clone</filename> command
|
||||
if you want to call the new directory something
|
||||
other than <filename>bitbake</filename>.
|
||||
Here is an example that names the directory
|
||||
<filename>bbdev</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.openembedded.org/bitbake bbdev
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para><emphasis>Installation using your Distribution
|
||||
Package Management System:</emphasis>
|
||||
This method is not
|
||||
recommended because the BitBake version that is
|
||||
provided by your distribution, in most cases,
|
||||
is several
|
||||
releases behind a snapshot of the BitBake repository.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Taking a snapshot of BitBake:</emphasis>
|
||||
Downloading a snapshot of BitBake from the
|
||||
source code repository gives you access to a known
|
||||
branch or release of BitBake.
|
||||
<note>
|
||||
Cloning the Git repository, as described earlier,
|
||||
is the preferred method for getting BitBake.
|
||||
Cloning the repository makes it easier to update as
|
||||
patches are added to the stable branches.
|
||||
</note></para>
|
||||
<para>The following example downloads a snapshot of
|
||||
BitBake version 1.17.0:
|
||||
<literallayout class='monospaced'>
|
||||
$ wget http://git.openembedded.org/bitbake/snapshot/bitbake-1.17.0.tar.gz
|
||||
$ tar zxpvf bitbake-1.17.0.tar.gz
|
||||
</literallayout>
|
||||
After extraction of the tarball using the tar utility,
|
||||
you have a directory entitled
|
||||
<filename>bitbake-1.17.0</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Using the BitBake that Comes With Your
|
||||
Build Checkout:</emphasis>
|
||||
A final possibility for getting a copy of BitBake is that it
|
||||
already comes with your checkout of a larger Bitbake-based build
|
||||
system, such as Poky.
|
||||
Rather than manually checking out individual layers and
|
||||
gluing them together yourself, you can check
|
||||
out an entire build system.
|
||||
The checkout will already include a version of BitBake that
|
||||
has been thoroughly tested for compatibility with the other
|
||||
components.
|
||||
For information on how to check out a particular BitBake-based
|
||||
build system, consult that build system's supporting documentation.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="bitbake-user-manual-command">
|
||||
<title>The BitBake Command</title>
|
||||
|
||||
<para>
|
||||
The <filename>bitbake</filename> command is the primary interface
|
||||
to the BitBake tool.
|
||||
This section presents the BitBake command syntax and provides
|
||||
several execution examples.
|
||||
</para>
|
||||
|
||||
<section id='usage-and-syntax'>
|
||||
<title>Usage and syntax</title>
|
||||
|
||||
<para>
|
||||
Following is the usage and syntax for BitBake:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -h
|
||||
Usage: bitbake [options] [recipename/target recipe:do_task ...]
|
||||
|
||||
Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
|
||||
It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
|
||||
will provide the layer, BBFILES and other configuration information.
|
||||
|
||||
Options:
|
||||
--version show program's version number and exit
|
||||
-h, --help show this help message and exit
|
||||
-b BUILDFILE, --buildfile=BUILDFILE
|
||||
Execute tasks from a specific .bb recipe directly.
|
||||
WARNING: Does not handle any dependencies from other
|
||||
recipes.
|
||||
-k, --continue Continue as much as possible after an error. While the
|
||||
target that failed and anything depending on it cannot
|
||||
be built, as much as possible will be built before
|
||||
stopping.
|
||||
-f, --force Force the specified targets/task to run (invalidating
|
||||
any existing stamp file).
|
||||
-c CMD, --cmd=CMD Specify the task to execute. The exact options
|
||||
available depend on the metadata. Some examples might
|
||||
be 'compile' or 'populate_sysroot' or 'listtasks' may
|
||||
give a list of the tasks available.
|
||||
-C INVALIDATE_STAMP, --clear-stamp=INVALIDATE_STAMP
|
||||
Invalidate the stamp for the specified task such as
|
||||
'compile' and then run the default task for the
|
||||
specified target(s).
|
||||
-r PREFILE, --read=PREFILE
|
||||
Read the specified file before bitbake.conf.
|
||||
-R POSTFILE, --postread=POSTFILE
|
||||
Read the specified file after bitbake.conf.
|
||||
-v, --verbose Enable tracing of shell tasks (with 'set -x'). Also
|
||||
print bb.note(...) messages to stdout (in addition to
|
||||
writing them to ${T}/log.do_<task>).
|
||||
-D, --debug Increase the debug level. You can specify this more
|
||||
than once. -D sets the debug level to 1, where only
|
||||
bb.debug(1, ...) messages are printed to stdout; -DD
|
||||
sets the debug level to 2, where both bb.debug(1, ...)
|
||||
and bb.debug(2, ...) messages are printed; etc.
|
||||
Without -D, no debug messages are printed. Note that
|
||||
-D only affects output to stdout. All debug messages
|
||||
are written to ${T}/log.do_taskname, regardless of the
|
||||
debug level.
|
||||
-q, --quiet Output less log message data to the terminal. You can
|
||||
specify this more than once.
|
||||
-n, --dry-run Don't execute, just go through the motions.
|
||||
-S SIGNATURE_HANDLER, --dump-signatures=SIGNATURE_HANDLER
|
||||
Dump out the signature construction information, with
|
||||
no task execution. The SIGNATURE_HANDLER parameter is
|
||||
passed to the handler. Two common values are none and
|
||||
printdiff but the handler may define more/less. none
|
||||
means only dump the signature, printdiff means compare
|
||||
the dumped signature with the cached one.
|
||||
-p, --parse-only Quit after parsing the BB recipes.
|
||||
-s, --show-versions Show current and preferred versions of all recipes.
|
||||
-e, --environment Show the global or per-recipe environment complete
|
||||
with information about where variables were
|
||||
set/changed.
|
||||
-g, --graphviz Save dependency tree information for the specified
|
||||
targets in the dot syntax.
|
||||
-I EXTRA_ASSUME_PROVIDED, --ignore-deps=EXTRA_ASSUME_PROVIDED
|
||||
Assume these dependencies don't exist and are already
|
||||
provided (equivalent to ASSUME_PROVIDED). Useful to
|
||||
make dependency graphs more appealing
|
||||
-l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
|
||||
Show debug logging for the specified logging domains
|
||||
-P, --profile Profile the command and save reports.
|
||||
-u UI, --ui=UI The user interface to use (knotty, ncurses or taskexp
|
||||
- default knotty).
|
||||
--token=XMLRPCTOKEN Specify the connection token to be used when
|
||||
connecting to a remote server.
|
||||
--revisions-changed Set the exit code depending on whether upstream
|
||||
floating revisions have changed or not.
|
||||
--server-only Run bitbake without a UI, only starting a server
|
||||
(cooker) process.
|
||||
-B BIND, --bind=BIND The name/address for the bitbake xmlrpc server to bind
|
||||
to.
|
||||
-T SERVER_TIMEOUT, --idle-timeout=SERVER_TIMEOUT
|
||||
Set timeout to unload bitbake server due to
|
||||
inactivity, set to -1 means no unload, default:
|
||||
Environment variable BB_SERVER_TIMEOUT.
|
||||
--no-setscene Do not run any setscene tasks. sstate will be ignored
|
||||
and everything needed, built.
|
||||
--setscene-only Only run setscene tasks, don't run any real tasks.
|
||||
--remote-server=REMOTE_SERVER
|
||||
Connect to the specified server.
|
||||
-m, --kill-server Terminate any running bitbake server.
|
||||
--observe-only Connect to a server as an observing-only client.
|
||||
--status-only Check the status of the remote bitbake server.
|
||||
-w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
|
||||
Writes the event log of the build to a bitbake event
|
||||
json file. Use '' (empty string) to assign the name
|
||||
automatically.
|
||||
--runall=RUNALL Run the specified task for any recipe in the taskgraph
|
||||
of the specified target (even if it wouldn't otherwise
|
||||
have run).
|
||||
--runonly=RUNONLY Run only the specified task within the taskgraph of
|
||||
the specified targets (and any task dependencies those
|
||||
tasks may have).
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bitbake-examples'>
|
||||
<title>Examples</title>
|
||||
|
||||
<para>
|
||||
This section presents some examples showing how to use BitBake.
|
||||
</para>
|
||||
|
||||
<section id='example-executing-a-task-against-a-single-recipe'>
|
||||
<title>Executing a Task Against a Single Recipe</title>
|
||||
|
||||
<para>
|
||||
Executing tasks for a single recipe file is relatively simple.
|
||||
You specify the file in question, and BitBake parses
|
||||
it and executes the specified task.
|
||||
If you do not specify a task, BitBake executes the default
|
||||
task, which is "build”.
|
||||
BitBake obeys inter-task dependencies when doing
|
||||
so.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following command runs the build task, which is
|
||||
the default task, on the <filename>foo_1.0.bb</filename>
|
||||
recipe file:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -b foo_1.0.bb
|
||||
</literallayout>
|
||||
The following command runs the clean task on the
|
||||
<filename>foo.bb</filename> recipe file:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -b foo.bb -c clean
|
||||
</literallayout>
|
||||
<note>
|
||||
The "-b" option explicitly does not handle recipe
|
||||
dependencies.
|
||||
Other than for debugging purposes, it is instead
|
||||
recommended that you use the syntax presented in the
|
||||
next section.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='executing-tasks-against-a-set-of-recipe-files'>
|
||||
<title>Executing Tasks Against a Set of Recipe Files</title>
|
||||
|
||||
<para>
|
||||
There are a number of additional complexities introduced
|
||||
when one wants to manage multiple <filename>.bb</filename>
|
||||
files.
|
||||
Clearly there needs to be a way to tell BitBake what
|
||||
files are available and, of those, which you
|
||||
want to execute.
|
||||
There also needs to be a way for each recipe
|
||||
to express its dependencies, both for build-time and
|
||||
runtime.
|
||||
There must be a way for you to express recipe preferences
|
||||
when multiple recipes provide the same functionality, or when
|
||||
there are multiple versions of a recipe.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>bitbake</filename> command, when not using
|
||||
"--buildfile" or "-b" only accepts a "PROVIDES".
|
||||
You cannot provide anything else.
|
||||
By default, a recipe file generally "PROVIDES" its
|
||||
"packagename" as shown in the following example:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake foo
|
||||
</literallayout>
|
||||
This next example "PROVIDES" the package name and also uses
|
||||
the "-c" option to tell BitBake to just execute the
|
||||
<filename>do_clean</filename> task:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -c clean foo
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='executing-a-list-of-task-and-recipe-combinations'>
|
||||
<title>Executing a List of Task and Recipe Combinations</title>
|
||||
|
||||
<para>
|
||||
The BitBake command line supports specifying different
|
||||
tasks for individual targets when you specify multiple
|
||||
targets.
|
||||
For example, suppose you had two targets (or recipes)
|
||||
<filename>myfirstrecipe</filename> and
|
||||
<filename>mysecondrecipe</filename> and you needed
|
||||
BitBake to run <filename>taskA</filename> for the first
|
||||
recipe and <filename>taskB</filename> for the second
|
||||
recipe:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake myfirstrecipe:do_taskA mysecondrecipe:do_taskB
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='generating-dependency-graphs'>
|
||||
<title>Generating Dependency Graphs</title>
|
||||
|
||||
<para>
|
||||
BitBake is able to generate dependency graphs using
|
||||
the <filename>dot</filename> syntax.
|
||||
You can convert these graphs into images using the
|
||||
<filename>dot</filename> tool from
|
||||
<ulink url='http://www.graphviz.org'>Graphviz</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you generate a dependency graph, BitBake writes three 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>).
|
||||
</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>
|
||||
Shows a simple list of targets that are to be built.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To stop depending on common depends, use the "-I" depend
|
||||
option and BitBake omits them from the graph.
|
||||
Leaving this information out can produce more readable graphs.
|
||||
This way, you can remove from the graph
|
||||
<filename>DEPENDS</filename> from inherited classes
|
||||
such as <filename>base.bbclass</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here are two examples that create dependency graphs.
|
||||
The second example omits depends common in OpenEmbedded from
|
||||
the graph:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -g foo
|
||||
|
||||
$ bitbake -g -I virtual/kernel -I eglibc foo
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='executing-a-multiple-configuration-build'>
|
||||
<title>Executing a Multiple Configuration Build</title>
|
||||
|
||||
<para>
|
||||
BitBake is able to build multiple images or packages
|
||||
using a single command where the different targets
|
||||
require different configurations (multiple configuration
|
||||
builds).
|
||||
Each target, in this scenario, is referred to as a
|
||||
"multiconfig".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To accomplish a multiple configuration build, you must
|
||||
define each target's configuration separately using
|
||||
a parallel configuration file in the build directory.
|
||||
The location for these multiconfig configuration files
|
||||
is specific.
|
||||
They must reside in the current build directory in
|
||||
a sub-directory of <filename>conf</filename> named
|
||||
<filename>multiconfig</filename>.
|
||||
Following is an example for two separate targets:
|
||||
<imagedata fileref="figures/bb_multiconfig_files.png" align="center" width="4in" depth="3in" />
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The reason for this required file hierarchy
|
||||
is because the <filename>BBPATH</filename> variable
|
||||
is not constructed until the layers are parsed.
|
||||
Consequently, using the configuration file as a
|
||||
pre-configuration file is not possible unless it is
|
||||
located in the current working directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Minimally, each configuration file must define the
|
||||
machine and the temporary directory BitBake uses
|
||||
for the build.
|
||||
Suggested practice dictates that you do not
|
||||
overlap the temporary directories used during the
|
||||
builds.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Aside from separate configuration files for each
|
||||
target, you must also enable BitBake to perform multiple
|
||||
configuration builds.
|
||||
Enabling is accomplished by setting the
|
||||
<link linkend='var-bb-BBMULTICONFIG'><filename>BBMULTICONFIG</filename></link>
|
||||
variable in the <filename>local.conf</filename>
|
||||
configuration file.
|
||||
As an example, suppose you had configuration files
|
||||
for <filename>target1</filename> and
|
||||
<filename>target2</filename> defined in the build
|
||||
directory.
|
||||
The following statement in the
|
||||
<filename>local.conf</filename> file both enables
|
||||
BitBake to perform multiple configuration builds and
|
||||
specifies the two multiconfigs:
|
||||
<literallayout class='monospaced'>
|
||||
BBMULTICONFIG = "target1 target2"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once the target configuration files are in place and
|
||||
BitBake has been enabled to perform multiple configuration
|
||||
builds, use the following command form to start the
|
||||
builds:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake [multiconfig:<replaceable>multiconfigname</replaceable>:]<replaceable>target</replaceable> [[[multiconfig:<replaceable>multiconfigname</replaceable>:]<replaceable>target</replaceable>] ... ]
|
||||
</literallayout>
|
||||
Here is an example for two multiconfigs:
|
||||
<filename>target1</filename> and
|
||||
<filename>target2</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake multiconfig:target1:<replaceable>target</replaceable> multiconfig:target2:<replaceable>target</replaceable>
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bb-enabling-multiple-configuration-build-dependencies'>
|
||||
<title>Enabling Multiple Configuration Build Dependencies</title>
|
||||
|
||||
<para>
|
||||
Sometimes dependencies can exist between targets
|
||||
(multiconfigs) in a multiple configuration build.
|
||||
For example, suppose that in order to build an image
|
||||
for a particular architecture, the root filesystem of
|
||||
another build for a different architecture needs to
|
||||
exist.
|
||||
In other words, the image for the first multiconfig depends
|
||||
on the root filesystem of the second multiconfig.
|
||||
This dependency is essentially that the task in the recipe
|
||||
that builds one multiconfig is dependent on the
|
||||
completion of the task in the recipe that builds
|
||||
another multiconfig.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To enable dependencies in a multiple configuration
|
||||
build, you must declare the dependencies in the recipe
|
||||
using the following statement form:
|
||||
<literallayout class='monospaced'>
|
||||
<replaceable>task_or_package</replaceable>[mcdepends] = "multiconfig:<replaceable>from_multiconfig</replaceable>:<replaceable>to_multiconfig</replaceable>:<replaceable>recipe_name</replaceable>:<replaceable>task_on_which_to_depend</replaceable>"
|
||||
</literallayout>
|
||||
To better show how to use this statement, consider an
|
||||
example with two multiconfigs: <filename>target1</filename>
|
||||
and <filename>target2</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
<replaceable>image_task</replaceable>[mcdepends] = "multiconfig:target1:target2:<replaceable>image2</replaceable>:<replaceable>rootfs_task</replaceable>"
|
||||
</literallayout>
|
||||
In this example, the
|
||||
<replaceable>from_multiconfig</replaceable> is "target1" and
|
||||
the <replaceable>to_multiconfig</replaceable> is "target2".
|
||||
The task on which the image whose recipe contains
|
||||
<replaceable>image_task</replaceable> depends on the
|
||||
completion of the <replaceable>rootfs_task</replaceable>
|
||||
used to build out <replaceable>image2</replaceable>, which
|
||||
is associated with the "target2" multiconfig.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you set up this dependency, you can build the
|
||||
"target1" multiconfig using a BitBake command as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake multiconfig:target1:<replaceable>image1</replaceable>
|
||||
</literallayout>
|
||||
This command executes all the tasks needed to create
|
||||
<replaceable>image1</replaceable> for the "target1"
|
||||
multiconfig.
|
||||
Because of the dependency, BitBake also executes through
|
||||
the <replaceable>rootfs_task</replaceable> for the "target2"
|
||||
multiconfig build.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Having a recipe depend on the root filesystem of another
|
||||
build might not seem that useful.
|
||||
Consider this change to the statement in the
|
||||
<replaceable>image1</replaceable> recipe:
|
||||
<literallayout class='monospaced'>
|
||||
<replaceable>image_task</replaceable>[mcdepends] = "multiconfig:target1:target2:<replaceable>image2</replaceable>:<replaceable>image_task</replaceable>"
|
||||
</literallayout>
|
||||
In this case, BitBake must create
|
||||
<replaceable>image2</replaceable> for the "target2"
|
||||
build since the "target1" build depends on it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Because "target1" and "target2" are enabled for multiple
|
||||
configuration builds and have separate configuration
|
||||
files, BitBake places the artifacts for each build in the
|
||||
respective temporary build directories.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
File diff suppressed because it is too large
Load Diff
2781
bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
Normal file
2781
bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,91 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
================
|
||||
Variable Context
|
||||
================
|
||||
|
||||
|
|
||||
|
||||
Variables might only have an impact or can be used in certain contexts. Some
|
||||
should only be used in global files like ``.conf``, while others are intended only
|
||||
for local files like ``.bb``. This chapter aims to describe some important variable
|
||||
contexts.
|
||||
|
||||
.. _ref-varcontext-configuration:
|
||||
|
||||
BitBake's own configuration
|
||||
===========================
|
||||
|
||||
Variables starting with ``BB_`` usually configure the behaviour of BitBake itself.
|
||||
For example, one could configure:
|
||||
|
||||
- System resources, like disk space to be used (:term:`BB_DISKMON_DIRS`),
|
||||
or the number of tasks to be run in parallel by BitBake (:term:`BB_NUMBER_THREADS`).
|
||||
|
||||
- How the fetchers shall behave, e.g., :term:`BB_FETCH_PREMIRRORONLY` is used
|
||||
by BitBake to determine if BitBake's fetcher shall search only
|
||||
:term:`PREMIRRORS` for files.
|
||||
|
||||
Those variables are usually configured globally.
|
||||
|
||||
BitBake configuration
|
||||
=====================
|
||||
|
||||
There are variables:
|
||||
|
||||
- Like :term:`B` or :term:`T`, that are used to specify directories used by
|
||||
BitBake during the build of a particular recipe. Those variables are
|
||||
specified in ``bitbake.conf``. Some, like :term:`B`, are quite often
|
||||
overwritten in recipes.
|
||||
|
||||
- Starting with ``FAKEROOT``, to configure how the ``fakeroot`` command is
|
||||
handled. Those are usually set by ``bitbake.conf`` and might get adapted in a
|
||||
``bbclass``.
|
||||
|
||||
- Detailing where BitBake will store and fetch information from, for
|
||||
data reuse between build runs like :term:`CACHE`, :term:`DL_DIR` or
|
||||
:term:`PERSISTENT_DIR`. Those are usually global.
|
||||
|
||||
|
||||
Layers and files
|
||||
================
|
||||
|
||||
Variables starting with ``LAYER`` configure how BitBake handles layers.
|
||||
Additionally, variables starting with ``BB`` configure how layers and files are
|
||||
handled. For example:
|
||||
|
||||
- :term:`LAYERDEPENDS` is used to configure on which layers a given layer
|
||||
depends.
|
||||
|
||||
- The configured layers are contained in :term:`BBLAYERS` and files in
|
||||
:term:`BBFILES`.
|
||||
|
||||
Those variables are often used in the files ``layer.conf`` and ``bblayers.conf``.
|
||||
|
||||
Recipes and packages
|
||||
====================
|
||||
|
||||
Variables handling recipes and packages can be split into:
|
||||
|
||||
- :term:`PN`, :term:`PV` or :term:`PF` for example, contain information about
|
||||
the name or revision of a recipe or package. Usually, the default set in
|
||||
``bitbake.conf`` is used, but those are from time to time overwritten in
|
||||
recipes.
|
||||
|
||||
- :term:`SUMMARY`, :term:`DESCRIPTION`, :term:`LICENSE` or :term:`HOMEPAGE`
|
||||
contain the expected information and should be set specifically for every
|
||||
recipe.
|
||||
|
||||
- In recipes, variables are also used to control build and runtime
|
||||
dependencies between recipes/packages with other recipes/packages. The
|
||||
most common should be: :term:`PROVIDES`, :term:`RPROVIDES`, :term:`DEPENDS`,
|
||||
and :term:`RDEPENDS`.
|
||||
|
||||
- There are further variables starting with ``SRC`` that specify the sources in
|
||||
a recipe like :term:`SRC_URI` or :term:`SRCDATE`. Those are also usually set
|
||||
in recipes.
|
||||
|
||||
- Which version or provider of a recipe should be given preference when
|
||||
multiple recipes would provide the same item, is controlled by variables
|
||||
starting with ``PREFERRED_``. Those are normally set in the configuration
|
||||
files of a ``MACHINE`` or ``DISTRO``.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
984
bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
Normal file
984
bitbake/doc/bitbake-user-manual/bitbake-user-manual-style.css
Normal file
@@ -0,0 +1,984 @@
|
||||
/*
|
||||
Generic XHTML / DocBook XHTML CSS Stylesheet.
|
||||
|
||||
Browser wrangling and typographic design by
|
||||
Oyvind Kolas / pippin@gimp.org
|
||||
|
||||
Customised for Poky by
|
||||
Matthew Allum / mallum@o-hand.com
|
||||
|
||||
Thanks to:
|
||||
Liam R. E. Quin
|
||||
William Skaggs
|
||||
Jakub Steiner
|
||||
|
||||
Structure
|
||||
---------
|
||||
|
||||
The stylesheet is divided into the following sections:
|
||||
|
||||
Positioning
|
||||
Margins, paddings, width, font-size, clearing.
|
||||
Decorations
|
||||
Borders, style
|
||||
Colors
|
||||
Colors
|
||||
Graphics
|
||||
Graphical backgrounds
|
||||
Nasty IE tweaks
|
||||
Workarounds needed to make it work in internet explorer,
|
||||
currently makes the stylesheet non validating, but up until
|
||||
this point it is validating.
|
||||
Mozilla extensions
|
||||
Transparency for footer
|
||||
Rounded corners on boxes
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*************** /
|
||||
/ Positioning /
|
||||
/ ***************/
|
||||
|
||||
body {
|
||||
font-family: Verdana, Sans, sans-serif;
|
||||
|
||||
min-width: 640px;
|
||||
width: 80%;
|
||||
margin: 0em auto;
|
||||
padding: 2em 5em 5em 5em;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6,h7 {
|
||||
font-family: Arial, Sans;
|
||||
color: #00557D;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
text-align: left;
|
||||
padding: 0em 0em 0em 0em;
|
||||
margin: 2em 0em 0em 0em;
|
||||
}
|
||||
|
||||
h2.subtitle {
|
||||
margin: 0.10em 0em 3.0em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
font-size: 1.8em;
|
||||
padding-left: 20%;
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 2em 0em 0.66em 0em;
|
||||
padding: 0.5em 0em 0em 0em;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h3.subtitle {
|
||||
margin: 0em 0em 1em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
font-size: 142.14%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.authorgroup {
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
padding-top: 256px;
|
||||
background-image: url("figures/bitbake-title.png");
|
||||
background-position: left top;
|
||||
margin-top: -256px;
|
||||
padding-right: 50px;
|
||||
margin-left: 0px;
|
||||
text-align: right;
|
||||
width: 740px;
|
||||
}
|
||||
|
||||
h3.author {
|
||||
margin: 0em 0me 0em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
font-weight: normal;
|
||||
font-size: 100%;
|
||||
color: #333;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.author tt.email {
|
||||
font-size: 66%;
|
||||
}
|
||||
|
||||
.titlepage hr {
|
||||
width: 0em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.revhistory {
|
||||
padding-top: 2em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.toc,
|
||||
.list-of-tables,
|
||||
.list-of-examples,
|
||||
.list-of-figures {
|
||||
padding: 1.33em 0em 2.5em 0em;
|
||||
color: #00557D;
|
||||
}
|
||||
|
||||
.toc p,
|
||||
.list-of-tables p,
|
||||
.list-of-figures p,
|
||||
.list-of-examples p {
|
||||
padding: 0em 0em 0em 0em;
|
||||
padding: 0em 0em 0.3em;
|
||||
margin: 1.5em 0em 0em 0em;
|
||||
}
|
||||
|
||||
.toc p b,
|
||||
.list-of-tables p b,
|
||||
.list-of-figures p b,
|
||||
.list-of-examples p b{
|
||||
font-size: 100.0%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.toc dl,
|
||||
.list-of-tables dl,
|
||||
.list-of-figures dl,
|
||||
.list-of-examples dl {
|
||||
margin: 0em 0em 0.5em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
.toc dt {
|
||||
margin: 0em 0em 0em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
.toc dd {
|
||||
margin: 0em 0em 0em 2.6em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
div.glossary dl,
|
||||
div.variablelist dl {
|
||||
}
|
||||
|
||||
.glossary dl dt,
|
||||
.variablelist dl dt,
|
||||
.variablelist dl dt span.term {
|
||||
font-weight: normal;
|
||||
width: 20em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.variablelist dl dt {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.glossary dl dd,
|
||||
.variablelist dl dd {
|
||||
margin-top: -1em;
|
||||
margin-left: 25.5em;
|
||||
}
|
||||
|
||||
.glossary dd p,
|
||||
.variablelist dd p {
|
||||
margin-top: 0em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
|
||||
div.calloutlist table td {
|
||||
padding: 0em 0em 0em 0em;
|
||||
margin: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
div.calloutlist table td p {
|
||||
margin-top: 0em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div p.copyright {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.legalnotice p.legalnotice-title {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.5em;
|
||||
margin-top: 0em;
|
||||
|
||||
}
|
||||
|
||||
dl {
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: solid 1px;
|
||||
}
|
||||
|
||||
|
||||
.mediaobject,
|
||||
.mediaobjectco {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0em 0em 0em 1.5em;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
ul li p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table {
|
||||
width :100%;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 0.25em;
|
||||
text-align: left;
|
||||
font-weight: normal;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0.25em;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
p a[id] {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
display: inline;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
/*font-weight: bold;*/
|
||||
}
|
||||
|
||||
/* This style defines how the permalink character
|
||||
appears by itself and when hovered over with
|
||||
the mouse. */
|
||||
|
||||
[alt='Permalink'] { color: #eee; }
|
||||
[alt='Permalink']:hover { color: black; }
|
||||
|
||||
|
||||
div.informalfigure,
|
||||
div.informalexample,
|
||||
div.informaltable,
|
||||
div.figure,
|
||||
div.table,
|
||||
div.example {
|
||||
margin: 1em 0em;
|
||||
padding: 1em;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
|
||||
div.informalfigure p.title b,
|
||||
div.informalexample p.title b,
|
||||
div.informaltable p.title b,
|
||||
div.figure p.title b,
|
||||
div.example p.title b,
|
||||
div.table p.title b{
|
||||
padding-top: 0em;
|
||||
margin-top: 0em;
|
||||
font-size: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.mediaobject .caption,
|
||||
.mediaobject .caption p {
|
||||
text-align: center;
|
||||
font-size: 80%;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.epigraph {
|
||||
padding-left: 55%;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.epigraph p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.epigraph .quote {
|
||||
font-style: italic;
|
||||
}
|
||||
.epigraph .attribution {
|
||||
font-style: normal;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
span.application {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.programlisting {
|
||||
font-family: monospace;
|
||||
font-size: 80%;
|
||||
white-space: pre;
|
||||
margin: 1.33em 0em;
|
||||
padding: 1.33em;
|
||||
}
|
||||
|
||||
.tip,
|
||||
.warning,
|
||||
.caution,
|
||||
.note {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
|
||||
}
|
||||
|
||||
/* force full width of table within div */
|
||||
.tip table,
|
||||
.warning table,
|
||||
.caution table,
|
||||
.note table {
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.tip table th,
|
||||
.warning table th,
|
||||
.caution table th,
|
||||
.note table th {
|
||||
padding: 0.8em 0.0em 0.0em 0.0em;
|
||||
margin : 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
.tip p,
|
||||
.warning p,
|
||||
.caution p,
|
||||
.note p {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
padding-right: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.acronym {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
b.keycap,
|
||||
.keycap {
|
||||
padding: 0.09em 0.3em;
|
||||
margin: 0em;
|
||||
}
|
||||
|
||||
.itemizedlist li {
|
||||
clear: none;
|
||||
}
|
||||
|
||||
.filename {
|
||||
font-size: medium;
|
||||
font-family: Courier, monospace;
|
||||
}
|
||||
|
||||
|
||||
div.navheader, div.heading{
|
||||
position: absolute;
|
||||
left: 0em;
|
||||
top: 0em;
|
||||
width: 100%;
|
||||
background-color: #cdf;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.navfooter, div.footing{
|
||||
position: fixed;
|
||||
left: 0em;
|
||||
bottom: 0em;
|
||||
background-color: #eee;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
div.navheader td,
|
||||
div.navfooter td {
|
||||
font-size: 66%;
|
||||
}
|
||||
|
||||
div.navheader table th {
|
||||
/*font-family: Georgia, Times, serif;*/
|
||||
/*font-size: x-large;*/
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
div.navheader table {
|
||||
border-left: 0em;
|
||||
border-right: 0em;
|
||||
border-top: 0em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.navfooter table {
|
||||
border-left: 0em;
|
||||
border-right: 0em;
|
||||
border-bottom: 0em;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.navheader table td a,
|
||||
div.navfooter table td a {
|
||||
color: #777;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* normal text in the footer */
|
||||
div.navfooter table td {
|
||||
color: black;
|
||||
}
|
||||
|
||||
div.navheader table td a:visited,
|
||||
div.navfooter table td a:visited {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
|
||||
/* links in header and footer */
|
||||
div.navheader table td a:hover,
|
||||
div.navfooter table td a:hover {
|
||||
text-decoration: underline;
|
||||
background-color: transparent;
|
||||
color: #33a;
|
||||
}
|
||||
|
||||
div.navheader hr,
|
||||
div.navfooter hr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.qandaset tr.question td p {
|
||||
margin: 0em 0em 1em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
|
||||
.qandaset tr.answer td p {
|
||||
margin: 0em 0em 1em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
}
|
||||
.answer td {
|
||||
padding-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.emphasis {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
/************* /
|
||||
/ decorations /
|
||||
/ *************/
|
||||
|
||||
.titlepage {
|
||||
}
|
||||
|
||||
.part .title {
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/*
|
||||
h1 {
|
||||
border: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
border-top: solid 0.2em;
|
||||
border-bottom: solid 0.06em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
border-top: 0em;
|
||||
border-bottom: solid 0.06em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
border: 0em;
|
||||
border-bottom: solid 0.06em;
|
||||
}
|
||||
|
||||
h5 {
|
||||
border: 0em;
|
||||
}
|
||||
*/
|
||||
|
||||
.programlisting {
|
||||
border: solid 1px;
|
||||
}
|
||||
|
||||
div.figure,
|
||||
div.table,
|
||||
div.informalfigure,
|
||||
div.informaltable,
|
||||
div.informalexample,
|
||||
div.example {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.tip,
|
||||
.warning,
|
||||
.caution,
|
||||
.note {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.tip table th,
|
||||
.warning table th,
|
||||
.caution table th,
|
||||
.note table th {
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
.question td {
|
||||
border-top: 1px solid black;
|
||||
}
|
||||
|
||||
.answer {
|
||||
}
|
||||
|
||||
|
||||
b.keycap,
|
||||
.keycap {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
|
||||
div.navheader, div.heading{
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
|
||||
div.navfooter, div.footing{
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
/********* /
|
||||
/ colors /
|
||||
/ *********/
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
background: white;
|
||||
}
|
||||
|
||||
a {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #dedede;
|
||||
}
|
||||
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
h7,
|
||||
h8 {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-color: #aaa;
|
||||
}
|
||||
|
||||
|
||||
.tip, .warning, .caution, .note {
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.tip table th,
|
||||
.warning table th,
|
||||
.caution table th,
|
||||
.note table th {
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.warning {
|
||||
background-color: #f0f0f2;
|
||||
}
|
||||
|
||||
.caution {
|
||||
background-color: #f0f0f2;
|
||||
}
|
||||
|
||||
.tip {
|
||||
background-color: #f0f0f2;
|
||||
}
|
||||
|
||||
.note {
|
||||
background-color: #f0f0f2;
|
||||
}
|
||||
|
||||
.glossary dl dt,
|
||||
.variablelist dl dt,
|
||||
.variablelist dl dt span.term {
|
||||
color: #044;
|
||||
}
|
||||
|
||||
div.figure,
|
||||
div.table,
|
||||
div.example,
|
||||
div.informalfigure,
|
||||
div.informaltable,
|
||||
div.informalexample {
|
||||
border-color: #aaa;
|
||||
}
|
||||
|
||||
pre.programlisting {
|
||||
color: black;
|
||||
background-color: #fff;
|
||||
border-color: #aaa;
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.guimenu,
|
||||
.guilabel,
|
||||
.guimenuitem {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
|
||||
b.keycap,
|
||||
.keycap {
|
||||
background-color: #eee;
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
|
||||
div.navheader {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
|
||||
div.navfooter {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
|
||||
/*********** /
|
||||
/ graphics /
|
||||
/ ***********/
|
||||
|
||||
/*
|
||||
body {
|
||||
background-image: url("images/body_bg.jpg");
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.navheader,
|
||||
.note,
|
||||
.tip {
|
||||
background-image: url("images/note_bg.jpg");
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.warning,
|
||||
.caution {
|
||||
background-image: url("images/warning_bg.jpg");
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.figure,
|
||||
.informalfigure,
|
||||
.example,
|
||||
.informalexample,
|
||||
.table,
|
||||
.informaltable {
|
||||
background-image: url("images/figure_bg.jpg");
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
*/
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
h7{
|
||||
}
|
||||
|
||||
/*
|
||||
Example of how to stick an image as part of the title.
|
||||
|
||||
div.article .titlepage .title
|
||||
{
|
||||
background-image: url("figures/white-on-black.png");
|
||||
background-position: center;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
*/
|
||||
|
||||
div.preface .titlepage .title,
|
||||
div.colophon .title,
|
||||
div.chapter .titlepage .title,
|
||||
div.article .titlepage .title
|
||||
{
|
||||
}
|
||||
|
||||
div.section div.section .titlepage .title,
|
||||
div.sect2 .titlepage .title {
|
||||
background: none;
|
||||
}
|
||||
|
||||
|
||||
h1.title {
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
height: 256px;
|
||||
text-indent: -9000px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
h2.subtitle {
|
||||
background-color: transparent;
|
||||
text-indent: -9000px;
|
||||
overflow:hidden;
|
||||
width: 0px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*************************************** /
|
||||
/ pippin.gimp.org specific alterations /
|
||||
/ ***************************************/
|
||||
|
||||
/*
|
||||
div.heading, div.navheader {
|
||||
color: #777;
|
||||
font-size: 80%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
background: url('/gfx/heading_bg.png') transparent;
|
||||
background-repeat: repeat-x;
|
||||
background-attachment: fixed;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.heading a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.footing, div.navfooter {
|
||||
border: none;
|
||||
color: #ddd;
|
||||
font-size: 80%;
|
||||
text-align:right;
|
||||
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
|
||||
background: url('/gfx/footing_bg.png') transparent;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/****************** /
|
||||
/ nasty ie tweaks /
|
||||
/ ******************/
|
||||
|
||||
/*
|
||||
div.heading, div.navheader {
|
||||
width:expression(document.body.clientWidth + "px");
|
||||
}
|
||||
|
||||
div.footing, div.navfooter {
|
||||
width:expression(document.body.clientWidth + "px");
|
||||
margin-left:expression("-5em");
|
||||
}
|
||||
body {
|
||||
padding:expression("4em 5em 0em 5em");
|
||||
}
|
||||
*/
|
||||
|
||||
/**************************************** /
|
||||
/ mozilla vendor specific css extensions /
|
||||
/ ****************************************/
|
||||
/*
|
||||
div.navfooter, div.footing{
|
||||
-moz-opacity: 0.8em;
|
||||
}
|
||||
|
||||
div.figure,
|
||||
div.table,
|
||||
div.informalfigure,
|
||||
div.informaltable,
|
||||
div.informalexample,
|
||||
div.example,
|
||||
.tip,
|
||||
.warning,
|
||||
.caution,
|
||||
.note {
|
||||
-moz-border-radius: 0.5em;
|
||||
}
|
||||
|
||||
b.keycap,
|
||||
.keycap {
|
||||
-moz-border-radius: 0.3em;
|
||||
}
|
||||
*/
|
||||
|
||||
table tr td table tr td {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
hr {
|
||||
display: none;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 0em;
|
||||
}
|
||||
|
||||
.photo {
|
||||
float: right;
|
||||
margin-left: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
margin-top: 0em;
|
||||
max-width: 17em;
|
||||
border: 1px solid gray;
|
||||
padding: 3px;
|
||||
background: white;
|
||||
}
|
||||
.seperator {
|
||||
padding-top: 2em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#validators {
|
||||
margin-top: 5em;
|
||||
text-align: right;
|
||||
color: #777;
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
font-size: 8pt;
|
||||
}
|
||||
.noprint {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.tip,
|
||||
.note {
|
||||
background: #f0f0f2;
|
||||
color: #333;
|
||||
padding: 20px;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
.tip h3,
|
||||
.note h3 {
|
||||
padding: 0em;
|
||||
margin: 0em;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.tip a,
|
||||
.note a {
|
||||
color: #333;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.footnote {
|
||||
font-size: small;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Changes the announcement text */
|
||||
.tip h3,
|
||||
.warning h3,
|
||||
.caution h3,
|
||||
.note h3 {
|
||||
font-size:large;
|
||||
color: #00557D;
|
||||
}
|
||||
88
bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
Normal file
88
bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
Normal file
@@ -0,0 +1,88 @@
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<book id='bitbake-user-manual' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
<bookinfo>
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/bitbake-title.png'
|
||||
format='SVG'
|
||||
align='left' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title>
|
||||
BitBake User Manual
|
||||
</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Richard Purdie, Chris Larson, and </firstname> <surname>Phil Blundell</surname>
|
||||
<affiliation>
|
||||
<orgname>BitBake Community</orgname>
|
||||
</affiliation>
|
||||
<email>bitbake-devel@lists.openembedded.org</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<!--
|
||||
# Add in some revision history if we want it here.
|
||||
<revhistory>
|
||||
<revision>
|
||||
<revnumber>x.x</revnumber>
|
||||
<date>dd month year</date>
|
||||
<revremark>Some relevent comment</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>x.x</revnumber>
|
||||
<date>dd month year</date>
|
||||
<revremark>Some relevent comment</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>x.x</revnumber>
|
||||
<date>dd month year</date>
|
||||
<revremark>Some relevent comment</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>x.x</revnumber>
|
||||
<date>dd month year</date>
|
||||
<revremark>Some relevent comment</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
-->
|
||||
|
||||
<copyright>
|
||||
<year>2004-2018</year>
|
||||
<holder>Richard Purdie</holder>
|
||||
<holder>Chris Larson</holder>
|
||||
<holder>and Phil Blundell</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
This work is licensed under the Creative Commons Attribution License.
|
||||
To view a copy of this license, visit
|
||||
<ulink url="http://creativecommons.org/licenses/by/2.5/">http://creativecommons.org/licenses/by/2.5/</ulink>
|
||||
or send a letter to Creative Commons, 444 Castro Street,
|
||||
Suite 900, Mountain View, California 94041, USA.
|
||||
</para>
|
||||
</legalnotice>
|
||||
</bookinfo>
|
||||
|
||||
<xi:include href="bitbake-user-manual-intro.xml"/>
|
||||
|
||||
<xi:include href="bitbake-user-manual-execution.xml"/>
|
||||
|
||||
<xi:include href="bitbake-user-manual-metadata.xml"/>
|
||||
|
||||
<xi:include href="bitbake-user-manual-fetching.xml"/>
|
||||
|
||||
<xi:include href="bitbake-user-manual-ref-variables.xml"/>
|
||||
|
||||
<xi:include href="bitbake-user-manual-hello.xml"/>
|
||||
|
||||
</book>
|
||||
281
bitbake/doc/bitbake-user-manual/html.css
Normal file
281
bitbake/doc/bitbake-user-manual/html.css
Normal file
@@ -0,0 +1,281 @@
|
||||
/* Feuille de style DocBook du projet Traduc.org */
|
||||
/* DocBook CSS stylesheet of the Traduc.org project */
|
||||
|
||||
/* (c) Jean-Philippe Gu<47>rard - 14 ao<61>t 2004 */
|
||||
/* (c) Jean-Philippe Gu<47>rard - 14 August 2004 */
|
||||
|
||||
/* Cette feuille de style est libre, vous pouvez la */
|
||||
/* redistribuer et la modifier selon les termes de la Licence */
|
||||
/* Art Libre. Vous trouverez un exemplaire de cette Licence sur */
|
||||
/* http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
|
||||
|
||||
/* This work of art is free, you can redistribute it and/or */
|
||||
/* modify it according to terms of the Free Art license. You */
|
||||
/* will find a specimen of this license on the Copyleft */
|
||||
/* Attitude web site: http://artlibre.org as well as on other */
|
||||
/* sites. */
|
||||
/* Please note that the French version of this licence as shown */
|
||||
/* on http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
|
||||
/* is only official licence of this document. The English */
|
||||
/* is only provided to help you understand this licence. */
|
||||
|
||||
/* La derni<6E>re version de cette feuille de style est toujours */
|
||||
/* disponible sur<75>: http://tigreraye.org/style.css */
|
||||
/* Elle est <20>galement disponible sur<75>: */
|
||||
/* http://www.traduc.org/docs/HOWTO/lecture/style.css */
|
||||
|
||||
/* The latest version of this stylesheet is available from: */
|
||||
/* http://tigreraye.org/style.css */
|
||||
/* It is also available on: */
|
||||
/* http://www.traduc.org/docs/HOWTO/lecture/style.css */
|
||||
|
||||
/* N'h<>sitez pas <20> envoyer vos commentaires et corrections <20> */
|
||||
/* Jean-Philippe Gu<47>rard <jean-philippe.guerard@tigreraye.org> */
|
||||
|
||||
/* Please send feedback and bug reports to */
|
||||
/* Jean-Philippe Gu<47>rard <jean-philippe.guerard@tigreraye.org> */
|
||||
|
||||
/* $Id: style.css,v 1.14 2004/09/10 20:12:09 fevrier Exp fevrier $ */
|
||||
|
||||
/* Pr<50>sentation g<>n<EFBFBD>rale du document */
|
||||
/* Overall document presentation */
|
||||
|
||||
body {
|
||||
/*
|
||||
font-family: Apolline, "URW Palladio L", Garamond, jGaramond,
|
||||
"Bitstream Cyberbit", "Palatino Linotype", serif;
|
||||
*/
|
||||
margin: 7%;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
/* Taille du texte */
|
||||
/* Text size */
|
||||
|
||||
* { font-size: 100%; }
|
||||
|
||||
/* Gestion des textes mis en relief imbriqu<71>s */
|
||||
/* Embedded emphasis */
|
||||
|
||||
em { font-style: italic; }
|
||||
em em { font-style: normal; }
|
||||
em em em { font-style: italic; }
|
||||
|
||||
/* Titres */
|
||||
/* Titles */
|
||||
|
||||
h1 { font-size: 200%; font-weight: 900; }
|
||||
h2 { font-size: 160%; font-weight: 900; }
|
||||
h3 { font-size: 130%; font-weight: bold; }
|
||||
h4 { font-size: 115%; font-weight: bold; }
|
||||
h5 { font-size: 108%; font-weight: bold; }
|
||||
h6 { font-weight: bold; }
|
||||
|
||||
/* Nom de famille en petites majuscules (uniquement en fran<61>ais) */
|
||||
/* Last names in small caps (for French only) */
|
||||
|
||||
*[class~="surname"]:lang(fr) { font-variant: small-caps; }
|
||||
|
||||
/* Blocs de citation */
|
||||
/* Quotation blocs */
|
||||
|
||||
div[class~="blockquote"] {
|
||||
border: solid 2px #AAA;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
div[class~="blockquote"] > table {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Blocs lit<69>raux<75>: fond gris clair */
|
||||
/* Literal blocs: light gray background */
|
||||
|
||||
*[class~="literallayout"] {
|
||||
background: #f0f0f0;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Programmes et captures texte<74>: fond bleu clair */
|
||||
/* Listing and text screen snapshots: light blue background */
|
||||
|
||||
*[class~="programlisting"], *[class~="screen"] {
|
||||
background: #f0f0ff;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Les textes <20> remplacer sont surlign<67>s en vert p<>le */
|
||||
/* Replaceable text in highlighted in pale green */
|
||||
|
||||
*[class~="replaceable"] {
|
||||
background-color: #98fb98;
|
||||
font-style: normal; }
|
||||
|
||||
/* Tables<65>: fonds gris clair & bords simples */
|
||||
/* Tables: light gray background and solid borders */
|
||||
|
||||
*[class~="table"] *[class~="title"] { width:100%; border: 0px; }
|
||||
|
||||
table {
|
||||
border: 1px solid #aaa;
|
||||
border-collapse: collapse;
|
||||
padding: 2px;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Listes simples en style table */
|
||||
/* Simples lists in table presentation */
|
||||
|
||||
table[class~="simplelist"] {
|
||||
background-color: #F0F0F0;
|
||||
margin: 5px;
|
||||
border: solid 1px #AAA;
|
||||
}
|
||||
|
||||
table[class~="simplelist"] td {
|
||||
border: solid 1px #AAA;
|
||||
}
|
||||
|
||||
/* Les tables */
|
||||
/* Tables */
|
||||
|
||||
*[class~="table"] table {
|
||||
background-color: #F0F0F0;
|
||||
border: solid 1px #AAA;
|
||||
}
|
||||
*[class~="informaltable"] table { background-color: #F0F0F0; }
|
||||
|
||||
th,td {
|
||||
vertical-align: baseline;
|
||||
text-align: left;
|
||||
padding: 0.1em 0.3em;
|
||||
empty-cells: show;
|
||||
}
|
||||
|
||||
/* Alignement des colonnes */
|
||||
/* Colunms alignment */
|
||||
|
||||
td[align=center] , th[align=center] { text-align: center; }
|
||||
td[align=right] , th[align=right] { text-align: right; }
|
||||
td[align=left] , th[align=left] { text-align: left; }
|
||||
td[align=justify] , th[align=justify] { text-align: justify; }
|
||||
|
||||
/* Pas de marge autour des images */
|
||||
/* No inside margins for images */
|
||||
|
||||
img { border: 0; }
|
||||
|
||||
/* Les liens ne sont pas soulign<67>s */
|
||||
/* No underlines for links */
|
||||
|
||||
:link , :visited , :active { text-decoration: none; }
|
||||
|
||||
/* Prudence<63>: cadre jaune et fond jaune clair */
|
||||
/* Caution: yellow border and light yellow background */
|
||||
|
||||
*[class~="caution"] {
|
||||
border: solid 2px yellow;
|
||||
background-color: #ffffe0;
|
||||
padding: 1em 6px 1em ;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
*[class~="caution"] th {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
*[class~="caution"] table {
|
||||
background-color: #ffffe0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Note importante<74>: cadre jaune et fond jaune clair */
|
||||
/* Important: yellow border and light yellow background */
|
||||
|
||||
*[class~="important"] {
|
||||
border: solid 2px yellow;
|
||||
background-color: #ffffe0;
|
||||
padding: 1em 6px 1em;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
*[class~="important"] th {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
*[class~="important"] table {
|
||||
background-color: #ffffe0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Mise en <20>vidence<63>: texte l<>g<EFBFBD>rement plus grand */
|
||||
/* Highlights: slightly larger texts */
|
||||
|
||||
*[class~="highlights"] {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
/* Note<74>: cadre bleu et fond bleu clair */
|
||||
/* Notes: blue border and light blue background */
|
||||
|
||||
*[class~="note"] {
|
||||
border: solid 2px #7099C5;
|
||||
background-color: #f0f0ff;
|
||||
padding: 1em 6px 1em ;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
*[class~="note"] th {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
*[class~="note"] table {
|
||||
background-color: #f0f0ff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Astuce<63>: cadre vert et fond vert clair */
|
||||
/* Tip: green border and light green background */
|
||||
|
||||
*[class~="tip"] {
|
||||
border: solid 2px #00ff00;
|
||||
background-color: #f0ffff;
|
||||
padding: 1em 6px 1em ;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
*[class~="tip"] th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
*[class~="tip"] table {
|
||||
background-color: #f0ffff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Avertissement<6E>: cadre rouge et fond rouge clair */
|
||||
/* Warning: red border and light red background */
|
||||
|
||||
*[class~="warning"] {
|
||||
border: solid 2px #ff0000;
|
||||
background-color: #fff0f0;
|
||||
padding: 1em 6px 1em ;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
*[class~="warning"] th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
*[class~="warning"] table {
|
||||
background-color: #fff0f0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* Fin */
|
||||
/* The End */
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
current_version = "dev"
|
||||
|
||||
# String used in sidebar
|
||||
version = 'Version: ' + current_version
|
||||
if current_version == 'dev':
|
||||
version = 'Version: Current Development'
|
||||
# Version seen in documentation_options.js and hence in js switchers code
|
||||
release = current_version
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'Bitbake'
|
||||
copyright = '2004-%s, Richard Purdie, Chris Larson, and Phil Blundell' \
|
||||
% datetime.datetime.now().year
|
||||
author = 'Richard Purdie, Chris Larson, and Phil Blundell'
|
||||
|
||||
# external links and substitutions
|
||||
extlinks = {
|
||||
'yocto_docs': ('https://docs.yoctoproject.org%s', None),
|
||||
'oe_lists': ('https://lists.openembedded.org%s', None),
|
||||
}
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'sphinx.ext.extlinks',
|
||||
]
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# master document name. The default changed from contents to index. so better
|
||||
# set it ourselves.
|
||||
master_doc = 'index'
|
||||
|
||||
# create substitution for project configuration variables
|
||||
rst_prolog = """
|
||||
.. |project_name| replace:: %s
|
||||
.. |copyright| replace:: %s
|
||||
.. |author| replace:: %s
|
||||
""" % (project, copyright, author)
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
except ImportError:
|
||||
sys.stderr.write("The Sphinx sphinx_rtd_theme HTML theme was not found.\
|
||||
\nPlease make sure to install the sphinx_rtd_theme python package.\n")
|
||||
sys.exit(1)
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['sphinx-static']
|
||||
|
||||
# Add customm CSS and JS files
|
||||
html_css_files = ['theme_overrides.css']
|
||||
html_js_files = ['switchers.js']
|
||||
|
||||
# Hide 'Created using Sphinx' text
|
||||
html_show_sphinx = False
|
||||
|
||||
# Add 'Last updated' on each page
|
||||
html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# Remove the trailing 'dot' in section numbers
|
||||
html_secnumber_suffix = " "
|
||||
@@ -1,3 +0,0 @@
|
||||
=====
|
||||
Index
|
||||
=====
|
||||
@@ -1,39 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
===================
|
||||
BitBake User Manual
|
||||
===================
|
||||
|
||||
|
|
||||
|
||||
.. toctree::
|
||||
:caption: Table of Contents
|
||||
:numbered:
|
||||
|
||||
bitbake-user-manual/bitbake-user-manual-intro
|
||||
bitbake-user-manual/bitbake-user-manual-execution
|
||||
bitbake-user-manual/bitbake-user-manual-metadata
|
||||
bitbake-user-manual/bitbake-user-manual-ref-variables-context
|
||||
bitbake-user-manual/bitbake-user-manual-fetching
|
||||
bitbake-user-manual/bitbake-user-manual-ref-variables
|
||||
bitbake-user-manual/bitbake-user-manual-hello
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
genindex
|
||||
releases
|
||||
|
||||
----
|
||||
|
||||
.. include:: <xhtml1-lat1.txt>
|
||||
|
||||
| BitBake Community
|
||||
| Copyright |copy| |copyright|
|
||||
| <bitbake-devel@lists.openembedded.org>
|
||||
|
||||
This work is licensed under the Creative Commons Attribution License. To view a
|
||||
copy of this license, visit http://creativecommons.org/licenses/by/2.5/ or send
|
||||
a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View,
|
||||
California 94041, USA.
|
||||
51
bitbake/doc/poky.ent
Normal file
51
bitbake/doc/poky.ent
Normal file
@@ -0,0 +1,51 @@
|
||||
<!ENTITY DISTRO "1.4">
|
||||
<!ENTITY DISTRO_NAME "tbd">
|
||||
<!ENTITY YOCTO_DOC_VERSION "1.4">
|
||||
<!ENTITY POKYVERSION "8.0">
|
||||
<!ENTITY YOCTO_POKY "poky-&DISTRO_NAME;-&POKYVERSION;">
|
||||
<!ENTITY COPYRIGHT_YEAR "2010-2013">
|
||||
<!ENTITY YOCTO_DL_URL "http://downloads.yoctoproject.org">
|
||||
<!ENTITY YOCTO_HOME_URL "http://www.yoctoproject.org">
|
||||
<!ENTITY YOCTO_LISTS_URL "http://lists.yoctoproject.org">
|
||||
<!ENTITY YOCTO_BUGZILLA_URL "http://bugzilla.yoctoproject.org">
|
||||
<!ENTITY YOCTO_WIKI_URL "https://wiki.yoctoproject.org">
|
||||
<!ENTITY YOCTO_AB_URL "http://autobuilder.yoctoproject.org">
|
||||
<!ENTITY YOCTO_GIT_URL "http://git.yoctoproject.org">
|
||||
<!ENTITY YOCTO_ADTREPO_URL "http://adtrepo.yoctoproject.org">
|
||||
<!ENTITY OE_HOME_URL "http://www.openembedded.org">
|
||||
<!ENTITY OE_LISTS_URL "http://lists.linuxtogo.org/cgi-bin/mailman">
|
||||
<!ENTITY OE_DOCS_URL "http://docs.openembedded.org">
|
||||
<!ENTITY OH_HOME_URL "http://o-hand.com">
|
||||
<!ENTITY BITBAKE_HOME_URL "http://developer.berlios.de/projects/bitbake/">
|
||||
<!ENTITY YOCTO_DOCS_URL "&YOCTO_HOME_URL;/docs">
|
||||
<!ENTITY YOCTO_SOURCES_URL "&YOCTO_HOME_URL;/sources/">
|
||||
<!ENTITY YOCTO_AB_PORT_URL "&YOCTO_AB_URL;:8010">
|
||||
<!ENTITY YOCTO_AB_NIGHTLY_URL "&YOCTO_AB_URL;/nightly/">
|
||||
<!ENTITY YOCTO_POKY_URL "&YOCTO_DL_URL;/releases/poky/">
|
||||
<!ENTITY YOCTO_RELEASE_DL_URL "&YOCTO_DL_URL;/releases/yocto/yocto-&DISTRO;">
|
||||
<!ENTITY YOCTO_TOOLCHAIN_DL_URL "&YOCTO_RELEASE_DL_URL;/toolchain/">
|
||||
<!ENTITY YOCTO_ADTINSTALLER_DL_URL "&YOCTO_RELEASE_DL_URL;/adt_installer">
|
||||
<!ENTITY YOCTO_POKY_DL_URL "&YOCTO_RELEASE_DL_URL;/&YOCTO_POKY;.tar.bz2">
|
||||
<!ENTITY YOCTO_MACHINES_DL_URL "&YOCTO_RELEASE_DL_URL;/machines">
|
||||
<!ENTITY YOCTO_QEMU_DL_URL "&YOCTO_MACHINES_DL_URL;/qemu">
|
||||
<!ENTITY YOCTO_PYTHON-i686_DL_URL "&YOCTO_DL_URL;/releases/miscsupport/python-nativesdk-standalone-i686.tar.bz2">
|
||||
<!ENTITY YOCTO_PYTHON-x86_64_DL_URL "&YOCTO_DL_URL;/releases/miscsupport/python-nativesdk-standalone-x86_64.tar.bz2">
|
||||
<!ENTITY YOCTO_DOCS_QS_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/yocto-project-qs/yocto-project-qs.html">
|
||||
<!ENTITY YOCTO_DOCS_ADT_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/adt-manual/adt-manual.html">
|
||||
<!ENTITY YOCTO_DOCS_REF_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/ref-manual/ref-manual.html">
|
||||
<!ENTITY YOCTO_DOCS_BSP_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/bsp-guide/bsp-guide.html">
|
||||
<!ENTITY YOCTO_DOCS_DEV_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/dev-manual/dev-manual.html">
|
||||
<!ENTITY YOCTO_DOCS_KERNEL_URL "&YOCTO_DOCS_URL;/&YOCTO_DOC_VERSION;/kernel-manual/kernel-manual.html">
|
||||
<!ENTITY YOCTO_ADTPATH_DIR "/opt/poky/&DISTRO;">
|
||||
<!ENTITY YOCTO_POKY_TARBALL "&YOCTO_POKY;.tar.bz2">
|
||||
<!ENTITY OE_INIT_PATH "&YOCTO_POKY;/oe-init-build-env">
|
||||
<!ENTITY OE_INIT_FILE "oe-init-build-env">
|
||||
<!ENTITY UBUNTU_HOST_PACKAGES_ESSENTIAL "gawk wget git-core diffstat unzip texinfo \
|
||||
build-essential chrpath">
|
||||
<!ENTITY FEDORA_HOST_PACKAGES_ESSENTIAL "gawk make wget tar bzip2 gzip python unzip perl patch \
|
||||
diffutils diffstat git cpp gcc gcc-c++ eglibc-devel texinfo chrpath \
|
||||
ccache">
|
||||
<!ENTITY OPENSUSE_HOST_PACKAGES_ESSENTIAL "python gcc gcc-c++ git chrpath make wget python-xml \
|
||||
diffstat texinfo python-curses">
|
||||
<!ENTITY CENTOS_HOST_PACKAGES_ESSENTIAL "gawk make wget tar bzip2 gzip python unzip perl patch \
|
||||
diffutils diffstat git cpp gcc gcc-c++ glibc-devel texinfo chrpath">
|
||||
@@ -1,186 +0,0 @@
|
||||
.. SPDX-License-Identifier: CC-BY-2.5
|
||||
|
||||
=================================
|
||||
BitBake Supported Release Manuals
|
||||
=================================
|
||||
|
||||
*******************************
|
||||
Release Series 5.0 (scarthgap)
|
||||
*******************************
|
||||
|
||||
- :yocto_docs:`BitBake 2.8 User Manual </bitbake/2.8/>`
|
||||
|
||||
******************************
|
||||
Release Series 4.0 (kirkstone)
|
||||
******************************
|
||||
|
||||
- :yocto_docs:`BitBake 2.0 User Manual </bitbake/2.0/>`
|
||||
|
||||
****************************
|
||||
Release Series 3.1 (dunfell)
|
||||
****************************
|
||||
|
||||
- :yocto_docs:`BitBake 1.46 User Manual </bitbake/1.46/>`
|
||||
|
||||
================================
|
||||
BitBake Outdated Release Manuals
|
||||
================================
|
||||
|
||||
*******************************
|
||||
Release Series 4.3 (nanbield)
|
||||
*******************************
|
||||
|
||||
- :yocto_docs:`BitBake 2.6 User Manual </bitbake/2.6/>`
|
||||
|
||||
*******************************
|
||||
Release Series 4.2 (mickledore)
|
||||
*******************************
|
||||
|
||||
- :yocto_docs:`BitBake 2.4 User Manual </bitbake/2.4/>`
|
||||
|
||||
*****************************
|
||||
Release Series 4.1 (langdale)
|
||||
*****************************
|
||||
|
||||
- :yocto_docs:`BitBake 2.2 User Manual </bitbake/2.2/>`
|
||||
|
||||
******************************
|
||||
Release Series 3.4 (honister)
|
||||
******************************
|
||||
|
||||
- :yocto_docs:`BitBake 1.52 User Manual </bitbake/1.52/>`
|
||||
|
||||
******************************
|
||||
Release Series 3.3 (hardknott)
|
||||
******************************
|
||||
|
||||
- :yocto_docs:`BitBake 1.50 User Manual </bitbake/1.50/>`
|
||||
|
||||
*******************************
|
||||
Release Series 3.2 (gatesgarth)
|
||||
*******************************
|
||||
|
||||
- :yocto_docs:`BitBake 1.48 User Manual </bitbake/1.48/>`
|
||||
|
||||
*******************************************
|
||||
Release Series 3.1 (dunfell first versions)
|
||||
*******************************************
|
||||
|
||||
- :yocto_docs:`3.1 BitBake User Manual </3.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.1.1 BitBake User Manual </3.1.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.1.2 BitBake User Manual </3.1.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.1.3 BitBake User Manual </3.1.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
*************************
|
||||
Release Series 3.0 (zeus)
|
||||
*************************
|
||||
|
||||
- :yocto_docs:`3.0 BitBake User Manual </3.0/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.0.1 BitBake User Manual </3.0.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.0.2 BitBake User Manual </3.0.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.0.3 BitBake User Manual </3.0.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`3.0.4 BitBake User Manual </3.0.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
****************************
|
||||
Release Series 2.7 (warrior)
|
||||
****************************
|
||||
|
||||
- :yocto_docs:`2.7 BitBake User Manual </2.7/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.7.1 BitBake User Manual </2.7.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.7.2 BitBake User Manual </2.7.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.7.3 BitBake User Manual </2.7.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.7.4 BitBake User Manual </2.7.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
*************************
|
||||
Release Series 2.6 (thud)
|
||||
*************************
|
||||
|
||||
- :yocto_docs:`2.6 BitBake User Manual </2.6/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.6.1 BitBake User Manual </2.6.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.6.2 BitBake User Manual </2.6.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.6.3 BitBake User Manual </2.6.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.6.4 BitBake User Manual </2.6.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
*************************
|
||||
Release Series 2.5 (sumo)
|
||||
*************************
|
||||
|
||||
- :yocto_docs:`2.5 Documentation </2.5>`
|
||||
- :yocto_docs:`2.5.1 Documentation </2.5.1>`
|
||||
- :yocto_docs:`2.5.2 Documentation </2.5.2>`
|
||||
- :yocto_docs:`2.5.3 Documentation </2.5.3>`
|
||||
|
||||
**************************
|
||||
Release Series 2.4 (rocko)
|
||||
**************************
|
||||
|
||||
- :yocto_docs:`2.4 BitBake User Manual </2.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.4.1 BitBake User Manual </2.4.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.4.2 BitBake User Manual </2.4.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.4.3 BitBake User Manual </2.4.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.4.4 BitBake User Manual </2.4.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
*************************
|
||||
Release Series 2.3 (pyro)
|
||||
*************************
|
||||
|
||||
- :yocto_docs:`2.3 BitBake User Manual </2.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.3.1 BitBake User Manual </2.3.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.3.2 BitBake User Manual </2.3.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.3.3 BitBake User Manual </2.3.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.3.4 BitBake User Manual </2.3.4/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
**************************
|
||||
Release Series 2.2 (morty)
|
||||
**************************
|
||||
|
||||
- :yocto_docs:`2.2 BitBake User Manual </2.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.2.1 BitBake User Manual </2.2.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.2.2 BitBake User Manual </2.2.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.2.3 BitBake User Manual </2.2.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
****************************
|
||||
Release Series 2.1 (krogoth)
|
||||
****************************
|
||||
|
||||
- :yocto_docs:`2.1 BitBake User Manual </2.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.1.1 BitBake User Manual </2.1.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.1.2 BitBake User Manual </2.1.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.1.3 BitBake User Manual </2.1.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
***************************
|
||||
Release Series 2.0 (jethro)
|
||||
***************************
|
||||
|
||||
- :yocto_docs:`1.9 BitBake User Manual </1.9/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.0 BitBake User Manual </2.0/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.0.1 BitBake User Manual </2.0.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.0.2 BitBake User Manual </2.0.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`2.0.3 BitBake User Manual </2.0.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
*************************
|
||||
Release Series 1.8 (fido)
|
||||
*************************
|
||||
|
||||
- :yocto_docs:`1.8 BitBake User Manual </1.8/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.8.1 BitBake User Manual </1.8.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.8.2 BitBake User Manual </1.8.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
**************************
|
||||
Release Series 1.7 (dizzy)
|
||||
**************************
|
||||
|
||||
- :yocto_docs:`1.7 BitBake User Manual </1.7/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.7.1 BitBake User Manual </1.7.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.7.2 BitBake User Manual </1.7.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.7.3 BitBake User Manual </1.7.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
**************************
|
||||
Release Series 1.6 (daisy)
|
||||
**************************
|
||||
|
||||
- :yocto_docs:`1.6 BitBake User Manual </1.6/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.6.1 BitBake User Manual </1.6.1/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.6.2 BitBake User Manual </1.6.2/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
- :yocto_docs:`1.6.3 BitBake User Manual </1.6.3/bitbake-user-manual/bitbake-user-manual.html>`
|
||||
|
||||
@@ -1,233 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var all_versions = {
|
||||
'dev': 'dev (3.2)',
|
||||
'3.1.2': '3.1.2',
|
||||
'3.0.3': '3.0.3',
|
||||
'2.7.4': '2.7.4',
|
||||
};
|
||||
|
||||
var all_doctypes = {
|
||||
'single': 'Individual Webpages',
|
||||
'mega': "All-in-one 'Mega' Manual",
|
||||
};
|
||||
|
||||
// Simple version comparision
|
||||
// Return 1 if a > b
|
||||
// Return -1 if a < b
|
||||
// Return 0 if a == b
|
||||
function ver_compare(a, b) {
|
||||
if (a == "dev") {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a === b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var a_components = a.split(".");
|
||||
var b_components = b.split(".");
|
||||
|
||||
var len = Math.min(a_components.length, b_components.length);
|
||||
|
||||
// loop while the components are equal
|
||||
for (var i = 0; i < len; i++) {
|
||||
// A bigger than B
|
||||
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// B bigger than A
|
||||
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// If one's a prefix of the other, the longer one is greater.
|
||||
if (a_components.length > b_components.length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a_components.length < b_components.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Otherwise they are the same.
|
||||
return 0;
|
||||
}
|
||||
|
||||
function build_version_select(current_series, current_version) {
|
||||
var buf = ['<select>'];
|
||||
|
||||
$.each(all_versions, function(version, title) {
|
||||
var series = version.substr(0, 3);
|
||||
if (series == current_series) {
|
||||
if (version == current_version)
|
||||
buf.push('<option value="' + version + '" selected="selected">' + title + '</option>');
|
||||
else
|
||||
buf.push('<option value="' + version + '">' + title + '</option>');
|
||||
|
||||
if (version != current_version)
|
||||
buf.push('<option value="' + current_version + '" selected="selected">' + current_version + '</option>');
|
||||
} else {
|
||||
buf.push('<option value="' + version + '">' + title + '</option>');
|
||||
}
|
||||
});
|
||||
|
||||
buf.push('</select>');
|
||||
return buf.join('');
|
||||
}
|
||||
|
||||
function build_doctype_select(current_doctype) {
|
||||
var buf = ['<select>'];
|
||||
|
||||
$.each(all_doctypes, function(doctype, title) {
|
||||
if (doctype == current_doctype)
|
||||
buf.push('<option value="' + doctype + '" selected="selected">' +
|
||||
all_doctypes[current_doctype] + '</option>');
|
||||
else
|
||||
buf.push('<option value="' + doctype + '">' + title + '</option>');
|
||||
});
|
||||
if (!(current_doctype in all_doctypes)) {
|
||||
// In case we're browsing a doctype that is not yet in all_doctypes.
|
||||
buf.push('<option value="' + current_doctype + '" selected="selected">' +
|
||||
current_doctype + '</option>');
|
||||
all_doctypes[current_doctype] = current_doctype;
|
||||
}
|
||||
buf.push('</select>');
|
||||
return buf.join('');
|
||||
}
|
||||
|
||||
function navigate_to_first_existing(urls) {
|
||||
// Navigate to the first existing URL in urls.
|
||||
var url = urls.shift();
|
||||
|
||||
// Web browsers won't redirect file:// urls to file urls using ajax but
|
||||
// its useful for local testing
|
||||
if (url.startsWith("file://")) {
|
||||
window.location.href = url;
|
||||
return;
|
||||
}
|
||||
|
||||
if (urls.length == 0) {
|
||||
window.location.href = url;
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: url,
|
||||
success: function() {
|
||||
window.location.href = url;
|
||||
},
|
||||
error: function() {
|
||||
navigate_to_first_existing(urls);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_docroot_url() {
|
||||
var url = window.location.href;
|
||||
var root = DOCUMENTATION_OPTIONS.URL_ROOT;
|
||||
|
||||
var urlarray = url.split('/');
|
||||
// Trim off anything after '/'
|
||||
urlarray.pop();
|
||||
var depth = (root.match(/\.\.\//g) || []).length;
|
||||
for (var i = 0; i < depth; i++) {
|
||||
urlarray.pop();
|
||||
}
|
||||
|
||||
return urlarray.join('/') + '/';
|
||||
}
|
||||
|
||||
function on_version_switch() {
|
||||
var selected_version = $(this).children('option:selected').attr('value');
|
||||
var url = window.location.href;
|
||||
var current_version = DOCUMENTATION_OPTIONS.VERSION;
|
||||
var docroot = get_docroot_url()
|
||||
|
||||
var new_versionpath = selected_version + '/';
|
||||
if (selected_version == "dev")
|
||||
new_versionpath = '';
|
||||
|
||||
// dev versions have no version prefix
|
||||
if (current_version == "dev") {
|
||||
var new_url = docroot + new_versionpath + url.replace(docroot, "");
|
||||
var fallback_url = docroot + new_versionpath;
|
||||
} else {
|
||||
var new_url = url.replace('/' + current_version + '/', '/' + new_versionpath);
|
||||
var fallback_url = new_url.replace(url.replace(docroot, ""), "");
|
||||
}
|
||||
|
||||
console.log(get_docroot_url())
|
||||
console.log(url + " to url " + new_url);
|
||||
console.log(url + " to fallback " + fallback_url);
|
||||
|
||||
if (new_url != url) {
|
||||
navigate_to_first_existing([
|
||||
new_url,
|
||||
fallback_url,
|
||||
'https://www.yoctoproject.org/docs/',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function on_doctype_switch() {
|
||||
var selected_doctype = $(this).children('option:selected').attr('value');
|
||||
var url = window.location.href;
|
||||
if (selected_doctype == 'mega') {
|
||||
var docroot = get_docroot_url()
|
||||
var current_version = DOCUMENTATION_OPTIONS.VERSION;
|
||||
// Assume manuals before 3.2 are using old docbook mega-manual
|
||||
if (ver_compare(current_version, "3.2") < 0) {
|
||||
var new_url = docroot + "mega-manual/mega-manual.html";
|
||||
} else {
|
||||
var new_url = docroot + "singleindex.html";
|
||||
}
|
||||
} else {
|
||||
var new_url = url.replace("singleindex.html", "index.html")
|
||||
}
|
||||
|
||||
if (new_url != url) {
|
||||
navigate_to_first_existing([
|
||||
new_url,
|
||||
'https://www.yoctoproject.org/docs/',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the current doctype based upon the url
|
||||
function doctype_segment_from_url(url) {
|
||||
if (url.includes("singleindex") || url.includes("mega-manual"))
|
||||
return "mega";
|
||||
return "single";
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
var release = DOCUMENTATION_OPTIONS.VERSION;
|
||||
var current_doctype = doctype_segment_from_url(window.location.href);
|
||||
var current_series = release.substr(0, 3);
|
||||
var version_select = build_version_select(current_series, release);
|
||||
|
||||
$('.version_switcher_placeholder').html(version_select);
|
||||
$('.version_switcher_placeholder select').bind('change', on_version_switch);
|
||||
|
||||
var doctype_select = build_doctype_select(current_doctype);
|
||||
|
||||
$('.doctype_switcher_placeholder').html(doctype_select);
|
||||
$('.doctype_switcher_placeholder select').bind('change', on_doctype_switch);
|
||||
|
||||
if (ver_compare(release, "3.1") < 0) {
|
||||
$('#outdated-warning').html('Version ' + release + ' of the project is now considered obsolete, please select and use a more recent version');
|
||||
$('#outdated-warning').css('padding', '.5em');
|
||||
} else if (release != "dev") {
|
||||
$.each(all_versions, function(version, title) {
|
||||
var series = version.substr(0, 3);
|
||||
if (series == current_series && version != release) {
|
||||
$('#outdated-warning').html('This document is for outdated version ' + release + ', you should select the latest release version in this series, ' + version + '.');
|
||||
$('#outdated-warning').css('padding', '.5em');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
SPDX-License-Identifier: CC-BY-2.0-UK
|
||||
*/
|
||||
|
||||
body {
|
||||
font-family: Verdana, Sans, sans-serif;
|
||||
margin: 0em auto;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6,h7 {
|
||||
font-family: Arial, Sans;
|
||||
color: #00557D;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
text-align: left;
|
||||
padding: 0em 0em 0em 0em;
|
||||
margin: 2em 0em 0em 0em;
|
||||
}
|
||||
|
||||
h2.subtitle {
|
||||
margin: 0.10em 0em 3.0em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
font-size: 1.8em;
|
||||
padding-left: 20%;
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 2em 0em 0.66em 0em;
|
||||
padding: 0.5em 0em 0em 0em;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h3.subtitle {
|
||||
margin: 0em 0em 1em 0em;
|
||||
padding: 0em 0em 0em 0em;
|
||||
font-size: 142.14%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h5 {
|
||||
margin: 1em 0em 0.5em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
em {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pre {
|
||||
font-size: medium;
|
||||
font-family: Courier, monospace;
|
||||
}
|
||||
|
||||
.wy-nav-content a {
|
||||
text-decoration: underline;
|
||||
color: #444;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.wy-nav-content a:hover {
|
||||
text-decoration: underline;
|
||||
background-color: #dedede;
|
||||
}
|
||||
|
||||
.wy-nav-content a:visited {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
[alt='Permalink'] { color: #eee; }
|
||||
[alt='Permalink']:hover { color: black; }
|
||||
|
||||
@media screen {
|
||||
/* content column
|
||||
*
|
||||
* RTD theme's default is 800px as max width for the content, but we have
|
||||
* tables with tons of columns, which need the full width of the view-port.
|
||||
*/
|
||||
|
||||
.wy-nav-content{max-width: none; }
|
||||
|
||||
/* inline literal: drop the borderbox, padding and red color */
|
||||
code, .rst-content tt, .rst-content code {
|
||||
color: inherit;
|
||||
border: none;
|
||||
padding: unset;
|
||||
background: inherit;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
.rst-content tt.literal,.rst-content tt.literal,.rst-content code.literal {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Admonition should be gray, not blue or green */
|
||||
.rst-content .note .admonition-title,
|
||||
.rst-content .tip .admonition-title,
|
||||
.rst-content .warning .admonition-title,
|
||||
.rst-content .caution .admonition-title,
|
||||
.rst-content .important .admonition-title {
|
||||
background: #f0f0f2;
|
||||
color: #00557D;
|
||||
|
||||
}
|
||||
|
||||
.rst-content .note,
|
||||
.rst-content .tip,
|
||||
.rst-content .important,
|
||||
.rst-content .warning,
|
||||
.rst-content .caution {
|
||||
background: #f0f0f2;
|
||||
}
|
||||
|
||||
/* Remove the icon in front of note/tip element, and before the logo */
|
||||
.icon-home:before, .rst-content .admonition-title:before {
|
||||
display: none
|
||||
}
|
||||
|
||||
/* a custom informalexample container is used in some doc */
|
||||
.informalexample {
|
||||
border: 1px solid;
|
||||
border-color: #aaa;
|
||||
margin: 1em 0em;
|
||||
padding: 1em;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
/* Remove the blue background in the top left corner, around the logo */
|
||||
.wy-side-nav-search {
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
}
|
||||
1
bitbake/doc/template/Vera.xml
vendored
Normal file
1
bitbake/doc/template/Vera.xml
vendored
Normal file
File diff suppressed because one or more lines are too long
1
bitbake/doc/template/VeraMoBd.xml
vendored
Normal file
1
bitbake/doc/template/VeraMoBd.xml
vendored
Normal file
File diff suppressed because one or more lines are too long
1
bitbake/doc/template/VeraMono.xml
vendored
Normal file
1
bitbake/doc/template/VeraMono.xml
vendored
Normal file
File diff suppressed because one or more lines are too long
39
bitbake/doc/template/component.title.xsl
vendored
Normal file
39
bitbake/doc/template/component.title.xsl
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:d="http://docbook.org/ns/docbook"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
exclude-result-prefixes="d">
|
||||
|
||||
<xsl:template name="component.title">
|
||||
<xsl:param name="node" select="."/>
|
||||
|
||||
<xsl:variable name="level">
|
||||
<xsl:choose>
|
||||
<xsl:when test="ancestor::d:section">
|
||||
<xsl:value-of select="count(ancestor::d:section)+1"/>
|
||||
</xsl:when>
|
||||
<xsl:when test="ancestor::d:sect5">6</xsl:when>
|
||||
<xsl:when test="ancestor::d:sect4">5</xsl:when>
|
||||
<xsl:when test="ancestor::d:sect3">4</xsl:when>
|
||||
<xsl:when test="ancestor::d:sect2">3</xsl:when>
|
||||
<xsl:when test="ancestor::d:sect1">2</xsl:when>
|
||||
<xsl:otherwise>1</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:element name="h{$level+1}" namespace="http://www.w3.org/1999/xhtml">
|
||||
<xsl:attribute name="class">title</xsl:attribute>
|
||||
<xsl:if test="$generate.id.attributes = 0">
|
||||
<xsl:call-template name="anchor">
|
||||
<xsl:with-param name="node" select="$node"/>
|
||||
<xsl:with-param name="conditional" select="0"/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="$node" mode="object.title.markup">
|
||||
<xsl:with-param name="allow-anchors" select="1"/>
|
||||
</xsl:apply-templates>
|
||||
<xsl:call-template name="permalink">
|
||||
<xsl:with-param name="node" select="$node"/>
|
||||
</xsl:call-template>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
64
bitbake/doc/template/db-pdf.xsl
vendored
Normal file
64
bitbake/doc/template/db-pdf.xsl
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl" />
|
||||
|
||||
<!-- check project-plan.sh for how this is generated, needed to tweak
|
||||
the cover page
|
||||
-->
|
||||
<xsl:include href="/tmp/titlepage.xsl"/>
|
||||
|
||||
<!-- To force a page break in document, i.e per section add a
|
||||
<?hard-pagebreak?> tag.
|
||||
-->
|
||||
<xsl:template match="processing-instruction('hard-pagebreak')">
|
||||
<fo:block break-before='page' />
|
||||
</xsl:template>
|
||||
|
||||
<!--Fix for defualt indent getting TOC all wierd..
|
||||
See http://sources.redhat.com/ml/docbook-apps/2005-q1/msg00455.html
|
||||
FIXME: must be a better fix
|
||||
-->
|
||||
<xsl:param name="body.start.indent" select="'0'"/>
|
||||
<!--<xsl:param name="title.margin.left" select="'0'"/>-->
|
||||
|
||||
<!-- stop long-ish header titles getting wrapped -->
|
||||
<xsl:param name="header.column.widths">1 10 1</xsl:param>
|
||||
|
||||
<!-- customise headers and footers a little -->
|
||||
|
||||
<xsl:template name="head.sep.rule">
|
||||
<xsl:if test="$header.rule != 0">
|
||||
<xsl:attribute name="border-bottom-width">0.5pt</xsl:attribute>
|
||||
<xsl:attribute name="border-bottom-style">solid</xsl:attribute>
|
||||
<xsl:attribute name="border-bottom-color">#cccccc</xsl:attribute>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="foot.sep.rule">
|
||||
<xsl:if test="$footer.rule != 0">
|
||||
<xsl:attribute name="border-top-width">0.5pt</xsl:attribute>
|
||||
<xsl:attribute name="border-top-style">solid</xsl:attribute>
|
||||
<xsl:attribute name="border-top-color">#cccccc</xsl:attribute>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:attribute-set name="header.content.properties">
|
||||
<xsl:attribute name="color">#cccccc</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
<xsl:attribute-set name="footer.content.properties">
|
||||
<xsl:attribute name="color">#cccccc</xsl:attribute>
|
||||
</xsl:attribute-set>
|
||||
|
||||
|
||||
<!-- general settings -->
|
||||
|
||||
<xsl:param name="fop1.extensions" select="1"></xsl:param>
|
||||
<xsl:param name="paper.type" select="'A4'"></xsl:param>
|
||||
<xsl:param name="section.autolabel" select="1"></xsl:param>
|
||||
<xsl:param name="body.font.family" select="'verasans'"></xsl:param>
|
||||
<xsl:param name="title.font.family" select="'verasans'"></xsl:param>
|
||||
<xsl:param name="monospace.font.family" select="'veramono'"></xsl:param>
|
||||
|
||||
</xsl:stylesheet>
|
||||
25
bitbake/doc/template/division.title.xsl
vendored
Normal file
25
bitbake/doc/template/division.title.xsl
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:d="http://docbook.org/ns/docbook"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
exclude-result-prefixes="d">
|
||||
|
||||
<xsl:template name="division.title">
|
||||
<xsl:param name="node" select="."/>
|
||||
|
||||
<h1>
|
||||
<xsl:attribute name="class">title</xsl:attribute>
|
||||
<xsl:call-template name="anchor">
|
||||
<xsl:with-param name="node" select="$node"/>
|
||||
<xsl:with-param name="conditional" select="0"/>
|
||||
</xsl:call-template>
|
||||
<xsl:apply-templates select="$node" mode="object.title.markup">
|
||||
<xsl:with-param name="allow-anchors" select="1"/>
|
||||
</xsl:apply-templates>
|
||||
<xsl:call-template name="permalink">
|
||||
<xsl:with-param name="node" select="$node"/>
|
||||
</xsl:call-template>
|
||||
</h1>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
|
||||
58
bitbake/doc/template/fop-config.xml
vendored
Normal file
58
bitbake/doc/template/fop-config.xml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<fop version="1.0">
|
||||
|
||||
<!-- Strict user configuration -->
|
||||
<strict-configuration>true</strict-configuration>
|
||||
|
||||
<!-- Strict FO validation -->
|
||||
<strict-validation>true</strict-validation>
|
||||
|
||||
<!--
|
||||
Set the baseDir so common/openedhand.svg references in plans still
|
||||
work ok. Note, relative file references to current dir should still work.
|
||||
-->
|
||||
<base>../template</base>
|
||||
<font-base>../template</font-base>
|
||||
|
||||
<!-- Source resolution in dpi (dots/pixels per inch) for determining the
|
||||
size of pixels in SVG and bitmap images, default: 72dpi -->
|
||||
<!-- <source-resolution>72</source-resolution> -->
|
||||
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the
|
||||
target resolution for generated bitmaps, default: 72dpi -->
|
||||
<!-- <target-resolution>72</target-resolution> -->
|
||||
|
||||
<!-- default page-height and page-width, in case
|
||||
value is specified as auto -->
|
||||
<default-page-settings height="11in" width="8.26in"/>
|
||||
|
||||
<!-- <use-cache>false</use-cache> -->
|
||||
|
||||
<renderers>
|
||||
<renderer mime="application/pdf">
|
||||
<fonts>
|
||||
<font metrics-file="VeraMono.xml"
|
||||
kerning="yes"
|
||||
embed-url="VeraMono.ttf">
|
||||
<font-triplet name="veramono" style="normal" weight="normal"/>
|
||||
</font>
|
||||
|
||||
<font metrics-file="VeraMoBd.xml"
|
||||
kerning="yes"
|
||||
embed-url="VeraMoBd.ttf">
|
||||
<font-triplet name="veramono" style="normal" weight="bold"/>
|
||||
</font>
|
||||
|
||||
<font metrics-file="Vera.xml"
|
||||
kerning="yes"
|
||||
embed-url="Vera.ttf">
|
||||
<font-triplet name="verasans" style="normal" weight="normal"/>
|
||||
<font-triplet name="verasans" style="normal" weight="bold"/>
|
||||
<font-triplet name="verasans" style="italic" weight="normal"/>
|
||||
<font-triplet name="verasans" style="italic" weight="bold"/>
|
||||
</font>
|
||||
|
||||
<auto-detect/>
|
||||
</fonts>
|
||||
</renderer>
|
||||
</renderers>
|
||||
</fop>
|
||||
|
||||
21
bitbake/doc/template/formal.object.heading.xsl
vendored
Normal file
21
bitbake/doc/template/formal.object.heading.xsl
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:d="http://docbook.org/ns/docbook"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
exclude-result-prefixes="d">
|
||||
|
||||
<xsl:template name="formal.object.heading">
|
||||
<xsl:param name="object" select="."/>
|
||||
<xsl:param name="title">
|
||||
<xsl:apply-templates select="$object" mode="object.title.markup">
|
||||
<xsl:with-param name="allow-anchors" select="1"/>
|
||||
</xsl:apply-templates>
|
||||
</xsl:param>
|
||||
<p class="title">
|
||||
<b><xsl:copy-of select="$title"/></b>
|
||||
<xsl:call-template name="permalink">
|
||||
<xsl:with-param name="node" select="$object"/>
|
||||
</xsl:call-template>
|
||||
</p>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
14
bitbake/doc/template/gloss-permalinks.xsl
vendored
Normal file
14
bitbake/doc/template/gloss-permalinks.xsl
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:d="http://docbook.org/ns/docbook"
|
||||
xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<xsl:template match="glossentry/glossterm">
|
||||
<xsl:apply-imports/>
|
||||
<xsl:if test="$generate.permalink != 0">
|
||||
<xsl:call-template name="permalink">
|
||||
<xsl:with-param name="node" select=".."/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
25
bitbake/doc/template/permalinks.xsl
vendored
Normal file
25
bitbake/doc/template/permalinks.xsl
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:param name="generate.permalink" select="1"/>
|
||||
<xsl:param name="permalink.text">¶</xsl:param>
|
||||
|
||||
<xsl:template name="permalink">
|
||||
<xsl:param name="node"/>
|
||||
|
||||
<xsl:if test="$generate.permalink != '0'">
|
||||
<span class="permalink">
|
||||
<a alt="Permalink" title="Permalink">
|
||||
<xsl:attribute name="href">
|
||||
<xsl:call-template name="href.target">
|
||||
<xsl:with-param name="object" select="$node"/>
|
||||
</xsl:call-template>
|
||||
</xsl:attribute>
|
||||
<xsl:copy-of select="$permalink.text"/>
|
||||
</a>
|
||||
</span>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
55
bitbake/doc/template/section.title.xsl
vendored
Normal file
55
bitbake/doc/template/section.title.xsl
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<xsl:stylesheet version="1.0"
|
||||
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:d="http://docbook.org/ns/docbook"
|
||||
xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="d">
|
||||
|
||||
<xsl:template name="section.title">
|
||||
<xsl:variable name="section"
|
||||
select="(ancestor::section |
|
||||
ancestor::simplesect|
|
||||
ancestor::sect1|
|
||||
ancestor::sect2|
|
||||
ancestor::sect3|
|
||||
ancestor::sect4|
|
||||
ancestor::sect5)[last()]"/>
|
||||
|
||||
<xsl:variable name="renderas">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$section/@renderas = 'sect1'">1</xsl:when>
|
||||
<xsl:when test="$section/@renderas = 'sect2'">2</xsl:when>
|
||||
<xsl:when test="$section/@renderas = 'sect3'">3</xsl:when>
|
||||
<xsl:when test="$section/@renderas = 'sect4'">4</xsl:when>
|
||||
<xsl:when test="$section/@renderas = 'sect5'">5</xsl:when>
|
||||
<xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="level">
|
||||
<xsl:choose>
|
||||
<xsl:when test="$renderas != ''">
|
||||
<xsl:value-of select="$renderas"/>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<xsl:call-template name="section.level">
|
||||
<xsl:with-param name="node" select="$section"/>
|
||||
</xsl:call-template>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:call-template name="section.heading">
|
||||
<xsl:with-param name="section" select="$section"/>
|
||||
<xsl:with-param name="level" select="$level"/>
|
||||
<xsl:with-param name="title">
|
||||
<xsl:apply-templates select="$section" mode="object.title.markup">
|
||||
<xsl:with-param name="allow-anchors" select="1"/>
|
||||
</xsl:apply-templates>
|
||||
<xsl:if test="$level > 0">
|
||||
<xsl:call-template name="permalink">
|
||||
<xsl:with-param name="node" select="$section"/>
|
||||
</xsl:call-template>
|
||||
</xsl:if>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
1259
bitbake/doc/template/titlepage.templates.xml
vendored
Normal file
1259
bitbake/doc/template/titlepage.templates.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
51
bitbake/doc/tools/docbook-to-pdf
Executable file
51
bitbake/doc/tools/docbook-to-pdf
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ -z "$1" -o -z "$2" ]; then
|
||||
echo "usage: [-v] $0 <docbook file> <templatedir>"
|
||||
echo
|
||||
echo "*NOTE* you need xsltproc, fop and nwalsh docbook stylesheets"
|
||||
echo " installed for this to work!"
|
||||
echo
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FO=`echo $1 | sed s/.xml/.fo/` || exit 1
|
||||
PDF=`echo $1 | sed s/.xml/.pdf/` || exit 1
|
||||
TEMPLATEDIR=$2
|
||||
|
||||
##
|
||||
# These URI should be rewritten by your distribution's xml catalog to
|
||||
# match your localy installed XSL stylesheets.
|
||||
XSL_BASE_URI="http://docbook.sourceforge.net/release/xsl/current"
|
||||
|
||||
# Creates a temporary XSL stylesheet based on titlepage.xsl
|
||||
xsltproc -o /tmp/titlepage.xsl \
|
||||
--xinclude \
|
||||
$XSL_BASE_URI/template/titlepage.xsl \
|
||||
$TEMPLATEDIR/titlepage.templates.xml || exit 1
|
||||
|
||||
# Creates the file needed for FOP
|
||||
xsltproc --xinclude \
|
||||
--stringparam hyphenate false \
|
||||
--stringparam formal.title.placement "figure after" \
|
||||
--stringparam ulink.show 1 \
|
||||
--stringparam body.font.master 9 \
|
||||
--stringparam title.font.master 11 \
|
||||
--stringparam draft.watermark.image "$TEMPLATEDIR/draft.png" \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam appendix.autolabel A \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--output $FO \
|
||||
$TEMPLATEDIR/db-pdf.xsl \
|
||||
$1 || exit 1
|
||||
|
||||
# Invokes the Java version of FOP. Uses the additional configuration file common/fop-config.xml
|
||||
fop -c $TEMPLATEDIR/fop-config.xml -fo $FO -pdf $PDF || exit 1
|
||||
|
||||
rm -f $FO
|
||||
rm -f /tmp/titlepage.xsl
|
||||
|
||||
echo
|
||||
echo " #### Success! $PDF ready. ####"
|
||||
echo
|
||||
@@ -1,18 +1,31 @@
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# This is a copy on write dictionary and set which abuses classes to try and be nice and fast.
|
||||
#
|
||||
# Copyright (C) 2006 Tim Ansell
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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.
|
||||
#
|
||||
# Please Note:
|
||||
# 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.
|
||||
#
|
||||
#Please Note:
|
||||
# Be careful when using mutable types (ie Dict and Lists) - operations involving these are SLOW.
|
||||
# Assign a file to __warn__ to get warnings about slow operations.
|
||||
#
|
||||
|
||||
|
||||
import copy
|
||||
|
||||
import types
|
||||
ImmutableTypes = (
|
||||
bool,
|
||||
complex,
|
||||
@@ -25,11 +38,9 @@ ImmutableTypes = (
|
||||
|
||||
MUTABLE = "__mutable__"
|
||||
|
||||
|
||||
class COWMeta(type):
|
||||
pass
|
||||
|
||||
|
||||
class COWDictMeta(COWMeta):
|
||||
__warn__ = False
|
||||
__hasmutable__ = False
|
||||
@@ -38,15 +49,12 @@ class COWDictMeta(COWMeta):
|
||||
def __str__(cls):
|
||||
# FIXME: I have magic numbers!
|
||||
return "<COWDict Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def cow(cls):
|
||||
class C(cls):
|
||||
__count__ = cls.__count__ + 1
|
||||
|
||||
return C
|
||||
|
||||
copy = cow
|
||||
__call__ = cow
|
||||
|
||||
@@ -78,9 +86,8 @@ class COWDictMeta(COWMeta):
|
||||
return value
|
||||
|
||||
__getmarker__ = []
|
||||
|
||||
def __getreadonly__(cls, key, default=__getmarker__):
|
||||
"""
|
||||
"""\
|
||||
Get a value (even if mutable) which you promise not to change.
|
||||
"""
|
||||
return cls.__getitem__(key, default, True)
|
||||
@@ -147,29 +154,24 @@ class COWDictMeta(COWMeta):
|
||||
|
||||
def iterkeys(cls):
|
||||
return cls.iter("keys")
|
||||
|
||||
def itervalues(cls, readonly=False):
|
||||
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
|
||||
print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
|
||||
print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
|
||||
return cls.iter("values", readonly)
|
||||
|
||||
def iteritems(cls, readonly=False):
|
||||
if not cls.__warn__ is False and cls.__hasmutable__ and readonly is False:
|
||||
print("Warning: If you aren't going to change any of the values call with True.", file=cls.__warn__)
|
||||
print("Warning: If you arn't going to change any of the values call with True.", file=cls.__warn__)
|
||||
return cls.iter("items", readonly)
|
||||
|
||||
|
||||
class COWSetMeta(COWDictMeta):
|
||||
def __str__(cls):
|
||||
# FIXME: I have magic numbers!
|
||||
return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) - 3)
|
||||
|
||||
return "<COWSet Level: %i Current Keys: %i>" % (cls.__count__, len(cls.__dict__) -3)
|
||||
__repr__ = __str__
|
||||
|
||||
def cow(cls):
|
||||
class C(cls):
|
||||
__count__ = cls.__count__ + 1
|
||||
|
||||
return C
|
||||
|
||||
def add(cls, value):
|
||||
@@ -187,11 +189,131 @@ class COWSetMeta(COWDictMeta):
|
||||
def iteritems(cls):
|
||||
raise TypeError("sets don't have 'items'")
|
||||
|
||||
|
||||
# These are the actual classes you use!
|
||||
class COWDictBase(metaclass=COWDictMeta):
|
||||
class COWDictBase(object, metaclass = COWDictMeta):
|
||||
__count__ = 0
|
||||
|
||||
|
||||
class COWSetBase(metaclass=COWSetMeta):
|
||||
class COWSetBase(object, metaclass = COWSetMeta):
|
||||
__count__ = 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
COWDictBase.__warn__ = sys.stderr
|
||||
a = COWDictBase()
|
||||
print("a", a)
|
||||
|
||||
a['a'] = 'a'
|
||||
a['b'] = 'b'
|
||||
a['dict'] = {}
|
||||
|
||||
b = a.copy()
|
||||
print("b", b)
|
||||
b['c'] = 'b'
|
||||
|
||||
print()
|
||||
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems():
|
||||
print(x)
|
||||
print()
|
||||
|
||||
b['dict']['a'] = 'b'
|
||||
b['a'] = 'c'
|
||||
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems():
|
||||
print(x)
|
||||
print()
|
||||
|
||||
try:
|
||||
b['dict2']
|
||||
except KeyError as e:
|
||||
print("Okay!")
|
||||
|
||||
a['set'] = COWSetBase()
|
||||
a['set'].add("o1")
|
||||
a['set'].add("o1")
|
||||
a['set'].add("o2")
|
||||
|
||||
print("a", a)
|
||||
for x in a['set'].itervalues():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b['set'].itervalues():
|
||||
print(x)
|
||||
print()
|
||||
|
||||
b['set'].add('o3')
|
||||
|
||||
print("a", a)
|
||||
for x in a['set'].itervalues():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b['set'].itervalues():
|
||||
print(x)
|
||||
print()
|
||||
|
||||
a['set2'] = set()
|
||||
a['set2'].add("o1")
|
||||
a['set2'].add("o1")
|
||||
a['set2'].add("o2")
|
||||
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems(readonly=True):
|
||||
print(x)
|
||||
print()
|
||||
|
||||
del b['b']
|
||||
try:
|
||||
print(b['b'])
|
||||
except KeyError:
|
||||
print("Yay! deleted key raises error")
|
||||
|
||||
if 'b' in b:
|
||||
print("Boo!")
|
||||
else:
|
||||
print("Yay - has_key with delete works!")
|
||||
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems(readonly=True):
|
||||
print(x)
|
||||
print()
|
||||
|
||||
b.__revertitem__('b')
|
||||
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems(readonly=True):
|
||||
print(x)
|
||||
print()
|
||||
|
||||
b.__revertitem__('dict')
|
||||
print("a", a)
|
||||
for x in a.iteritems():
|
||||
print(x)
|
||||
print("--")
|
||||
print("b", b)
|
||||
for x in b.iteritems(readonly=True):
|
||||
print(x)
|
||||
print()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# BitBake Build System Python Library
|
||||
#
|
||||
@@ -6,73 +8,54 @@
|
||||
#
|
||||
# Based on Gentoo's portage.py.
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
# 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.
|
||||
|
||||
__version__ = "2.9.1"
|
||||
__version__ = "1.42.0"
|
||||
|
||||
import sys
|
||||
if sys.version_info < (3, 8, 0):
|
||||
raise RuntimeError("Sorry, python 3.8.0 or later is required for this version of bitbake")
|
||||
if sys.version_info < (3, 4, 0):
|
||||
raise RuntimeError("Sorry, python 3.4.0 or later is required for this version of bitbake")
|
||||
|
||||
if sys.version_info < (3, 10, 0):
|
||||
# With python 3.8 and 3.9, we see errors of "libgcc_s.so.1 must be installed for pthread_cancel to work"
|
||||
# https://stackoverflow.com/questions/64797838/libgcc-s-so-1-must-be-installed-for-pthread-cancel-to-work
|
||||
# https://bugs.ams1.psf.io/issue42888
|
||||
# so ensure libgcc_s is loaded early on
|
||||
import ctypes
|
||||
libgcc_s = ctypes.CDLL('libgcc_s.so.1')
|
||||
|
||||
class BBHandledException(Exception):
|
||||
"""
|
||||
The big dilemma for generic bitbake code is what information to give the user
|
||||
when an exception occurs. Any exception inheriting this base exception class
|
||||
has already provided information to the user via some 'fired' message type such as
|
||||
an explicitly fired event using bb.fire, or a bb.error message. If bitbake
|
||||
encounters an exception derived from this class, no backtrace or other information
|
||||
an explicitly fired event using bb.fire, or a bb.error message. If bitbake
|
||||
encounters an exception derived from this class, no backtrace or other information
|
||||
will be given to the user, its assumed the earlier event provided the relevant information.
|
||||
"""
|
||||
pass
|
||||
|
||||
import os
|
||||
import logging
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
class BBLoggerMixin(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
# Does nothing to allow calling super() from derived classes
|
||||
pass
|
||||
|
||||
def setup_bblogger(self, name):
|
||||
Logger = logging.getLoggerClass()
|
||||
class BBLogger(Logger):
|
||||
def __init__(self, name):
|
||||
if name.split(".")[0] == "BitBake":
|
||||
self.debug = self._debug_helper
|
||||
|
||||
def _debug_helper(self, *args, **kwargs):
|
||||
return self.bbdebug(1, *args, **kwargs)
|
||||
|
||||
def debug2(self, *args, **kwargs):
|
||||
return self.bbdebug(2, *args, **kwargs)
|
||||
|
||||
def debug3(self, *args, **kwargs):
|
||||
return self.bbdebug(3, *args, **kwargs)
|
||||
self.debug = self.bbdebug
|
||||
Logger.__init__(self, name)
|
||||
|
||||
def bbdebug(self, level, msg, *args, **kwargs):
|
||||
loglevel = logging.DEBUG - level + 1
|
||||
if not bb.event.worker_pid:
|
||||
if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
|
||||
return
|
||||
if loglevel < bb.msg.loggerDefaultLogLevel:
|
||||
return
|
||||
|
||||
if not isinstance(level, int) or not isinstance(msg, str):
|
||||
mainlogger.warning("Invalid arguments in bbdebug: %s" % repr((level, msg,) + args))
|
||||
|
||||
return self.log(loglevel, msg, *args, **kwargs)
|
||||
return self.log(logging.DEBUG - level + 1, msg, *args, **kwargs)
|
||||
|
||||
def plain(self, msg, *args, **kwargs):
|
||||
return self.log(logging.INFO + 1, msg, *args, **kwargs)
|
||||
@@ -83,43 +66,16 @@ class BBLoggerMixin(object):
|
||||
def verbnote(self, msg, *args, **kwargs):
|
||||
return self.log(logging.INFO + 2, msg, *args, **kwargs)
|
||||
|
||||
def warnonce(self, msg, *args, **kwargs):
|
||||
return self.log(logging.WARNING - 1, msg, *args, **kwargs)
|
||||
|
||||
def erroronce(self, msg, *args, **kwargs):
|
||||
return self.log(logging.ERROR - 1, msg, *args, **kwargs)
|
||||
|
||||
|
||||
Logger = logging.getLoggerClass()
|
||||
class BBLogger(Logger, BBLoggerMixin):
|
||||
def __init__(self, name, *args, **kwargs):
|
||||
self.setup_bblogger(name)
|
||||
super().__init__(name, *args, **kwargs)
|
||||
|
||||
logging.raiseExceptions = False
|
||||
logging.setLoggerClass(BBLogger)
|
||||
|
||||
class BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
|
||||
def __init__(self, logger, *args, **kwargs):
|
||||
self.setup_bblogger(logger.name)
|
||||
super().__init__(logger, *args, **kwargs)
|
||||
|
||||
logging.LoggerAdapter = BBLoggerAdapter
|
||||
|
||||
logger = logging.getLogger("BitBake")
|
||||
logger.addHandler(NullHandler())
|
||||
logger.setLevel(logging.DEBUG - 2)
|
||||
|
||||
mainlogger = logging.getLogger("BitBake.Main")
|
||||
|
||||
class PrefixLoggerAdapter(logging.LoggerAdapter):
|
||||
def __init__(self, prefix, logger):
|
||||
super().__init__(logger, {})
|
||||
self.__msg_prefix = prefix
|
||||
|
||||
def process(self, msg, kwargs):
|
||||
return "%s%s" %(self.__msg_prefix, msg), kwargs
|
||||
|
||||
# This has to be imported after the setLoggerClass, as the import of bb.msg
|
||||
# can result in construction of the various loggers.
|
||||
import bb.msg
|
||||
@@ -136,7 +92,7 @@ def debug(lvl, *args):
|
||||
mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
|
||||
args = (lvl,) + args
|
||||
lvl = 1
|
||||
mainlogger.bbdebug(lvl, ''.join(args))
|
||||
mainlogger.debug(lvl, ''.join(args))
|
||||
|
||||
def note(*args):
|
||||
mainlogger.info(''.join(args))
|
||||
@@ -156,15 +112,9 @@ def verbnote(*args):
|
||||
def warn(*args):
|
||||
mainlogger.warning(''.join(args))
|
||||
|
||||
def warnonce(*args):
|
||||
mainlogger.warnonce(''.join(args))
|
||||
|
||||
def error(*args, **kwargs):
|
||||
mainlogger.error(''.join(args), extra=kwargs)
|
||||
|
||||
def erroronce(*args):
|
||||
mainlogger.erroronce(''.join(args))
|
||||
|
||||
def fatal(*args, **kwargs):
|
||||
mainlogger.critical(''.join(args), extra=kwargs)
|
||||
raise BBHandledException()
|
||||
@@ -208,14 +158,3 @@ def deprecate_import(current, modulename, fromlist, renames = None):
|
||||
|
||||
setattr(sys.modules[current], newname, newobj)
|
||||
|
||||
TaskData = namedtuple("TaskData", [
|
||||
"pn",
|
||||
"taskname",
|
||||
"fn",
|
||||
"deps",
|
||||
"provides",
|
||||
"taskhash",
|
||||
"unihash",
|
||||
"hashfn",
|
||||
"taskhash_deps",
|
||||
])
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
#! /usr/bin/env python3
|
||||
#
|
||||
# Copyright 2023 by Garmin Ltd. or its subsidiaries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
import sys
|
||||
import ctypes
|
||||
import os
|
||||
import errno
|
||||
import pwd
|
||||
import grp
|
||||
|
||||
libacl = ctypes.CDLL("libacl.so.1", use_errno=True)
|
||||
|
||||
|
||||
ACL_TYPE_ACCESS = 0x8000
|
||||
ACL_TYPE_DEFAULT = 0x4000
|
||||
|
||||
ACL_FIRST_ENTRY = 0
|
||||
ACL_NEXT_ENTRY = 1
|
||||
|
||||
ACL_UNDEFINED_TAG = 0x00
|
||||
ACL_USER_OBJ = 0x01
|
||||
ACL_USER = 0x02
|
||||
ACL_GROUP_OBJ = 0x04
|
||||
ACL_GROUP = 0x08
|
||||
ACL_MASK = 0x10
|
||||
ACL_OTHER = 0x20
|
||||
|
||||
ACL_READ = 0x04
|
||||
ACL_WRITE = 0x02
|
||||
ACL_EXECUTE = 0x01
|
||||
|
||||
acl_t = ctypes.c_void_p
|
||||
acl_entry_t = ctypes.c_void_p
|
||||
acl_permset_t = ctypes.c_void_p
|
||||
acl_perm_t = ctypes.c_uint
|
||||
|
||||
acl_tag_t = ctypes.c_int
|
||||
|
||||
libacl.acl_free.argtypes = [acl_t]
|
||||
|
||||
|
||||
def acl_free(acl):
|
||||
libacl.acl_free(acl)
|
||||
|
||||
|
||||
libacl.acl_get_file.restype = acl_t
|
||||
libacl.acl_get_file.argtypes = [ctypes.c_char_p, ctypes.c_uint]
|
||||
|
||||
|
||||
def acl_get_file(path, typ):
|
||||
acl = libacl.acl_get_file(os.fsencode(path), typ)
|
||||
if acl is None:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err), str(path))
|
||||
|
||||
return acl
|
||||
|
||||
|
||||
libacl.acl_get_entry.argtypes = [acl_t, ctypes.c_int, ctypes.c_void_p]
|
||||
|
||||
|
||||
def acl_get_entry(acl, entry_id):
|
||||
entry = acl_entry_t()
|
||||
ret = libacl.acl_get_entry(acl, entry_id, ctypes.byref(entry))
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
|
||||
if ret == 0:
|
||||
return None
|
||||
|
||||
return entry
|
||||
|
||||
|
||||
libacl.acl_get_tag_type.argtypes = [acl_entry_t, ctypes.c_void_p]
|
||||
|
||||
|
||||
def acl_get_tag_type(entry_d):
|
||||
tag = acl_tag_t()
|
||||
ret = libacl.acl_get_tag_type(entry_d, ctypes.byref(tag))
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
return tag.value
|
||||
|
||||
|
||||
libacl.acl_get_qualifier.restype = ctypes.c_void_p
|
||||
libacl.acl_get_qualifier.argtypes = [acl_entry_t]
|
||||
|
||||
|
||||
def acl_get_qualifier(entry_d):
|
||||
ret = libacl.acl_get_qualifier(entry_d)
|
||||
if ret is None:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
return ctypes.c_void_p(ret)
|
||||
|
||||
|
||||
libacl.acl_get_permset.argtypes = [acl_entry_t, ctypes.c_void_p]
|
||||
|
||||
|
||||
def acl_get_permset(entry_d):
|
||||
permset = acl_permset_t()
|
||||
ret = libacl.acl_get_permset(entry_d, ctypes.byref(permset))
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
|
||||
return permset
|
||||
|
||||
|
||||
libacl.acl_get_perm.argtypes = [acl_permset_t, acl_perm_t]
|
||||
|
||||
|
||||
def acl_get_perm(permset_d, perm):
|
||||
ret = libacl.acl_get_perm(permset_d, perm)
|
||||
if ret < 0:
|
||||
err = ctypes.get_errno()
|
||||
raise OSError(err, os.strerror(err))
|
||||
return bool(ret)
|
||||
|
||||
|
||||
class Entry(object):
|
||||
def __init__(self, tag, qualifier, mode):
|
||||
self.tag = tag
|
||||
self.qualifier = qualifier
|
||||
self.mode = mode
|
||||
|
||||
def __str__(self):
|
||||
typ = ""
|
||||
qual = ""
|
||||
if self.tag == ACL_USER:
|
||||
typ = "user"
|
||||
qual = pwd.getpwuid(self.qualifier).pw_name
|
||||
elif self.tag == ACL_GROUP:
|
||||
typ = "group"
|
||||
qual = grp.getgrgid(self.qualifier).gr_name
|
||||
elif self.tag == ACL_USER_OBJ:
|
||||
typ = "user"
|
||||
elif self.tag == ACL_GROUP_OBJ:
|
||||
typ = "group"
|
||||
elif self.tag == ACL_MASK:
|
||||
typ = "mask"
|
||||
elif self.tag == ACL_OTHER:
|
||||
typ = "other"
|
||||
|
||||
r = "r" if self.mode & ACL_READ else "-"
|
||||
w = "w" if self.mode & ACL_WRITE else "-"
|
||||
x = "x" if self.mode & ACL_EXECUTE else "-"
|
||||
|
||||
return f"{typ}:{qual}:{r}{w}{x}"
|
||||
|
||||
|
||||
class ACL(object):
|
||||
def __init__(self, acl):
|
||||
self.acl = acl
|
||||
|
||||
def __del__(self):
|
||||
acl_free(self.acl)
|
||||
|
||||
def entries(self):
|
||||
entry_id = ACL_FIRST_ENTRY
|
||||
while True:
|
||||
entry = acl_get_entry(self.acl, entry_id)
|
||||
if entry is None:
|
||||
break
|
||||
|
||||
permset = acl_get_permset(entry)
|
||||
|
||||
mode = 0
|
||||
for m in (ACL_READ, ACL_WRITE, ACL_EXECUTE):
|
||||
if acl_get_perm(permset, m):
|
||||
mode |= m
|
||||
|
||||
qualifier = None
|
||||
tag = acl_get_tag_type(entry)
|
||||
|
||||
if tag == ACL_USER or tag == ACL_GROUP:
|
||||
qual = acl_get_qualifier(entry)
|
||||
qualifier = ctypes.cast(qual, ctypes.POINTER(ctypes.c_int))[0]
|
||||
|
||||
yield Entry(tag, qualifier, mode)
|
||||
|
||||
entry_id = ACL_NEXT_ENTRY
|
||||
|
||||
@classmethod
|
||||
def from_path(cls, path, typ):
|
||||
acl = acl_get_file(path, typ)
|
||||
return cls(acl)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
import pwd
|
||||
import grp
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("path", help="File Path", type=Path)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
acl = ACL.from_path(args.path, ACL_TYPE_ACCESS)
|
||||
for entry in acl.entries():
|
||||
print(str(entry))
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
|
||||
from .client import AsyncClient, Client
|
||||
from .serv import AsyncServer, AsyncServerConnection
|
||||
from .connection import DEFAULT_MAX_CHUNK
|
||||
from .exceptions import (
|
||||
ClientError,
|
||||
ServerError,
|
||||
ConnectionClosedError,
|
||||
InvokeError,
|
||||
)
|
||||
@@ -1,266 +0,0 @@
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import abc
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import re
|
||||
import contextlib
|
||||
from threading import Thread
|
||||
from .connection import StreamConnection, WebsocketConnection, DEFAULT_MAX_CHUNK
|
||||
from .exceptions import ConnectionClosedError, InvokeError
|
||||
|
||||
UNIX_PREFIX = "unix://"
|
||||
WS_PREFIX = "ws://"
|
||||
WSS_PREFIX = "wss://"
|
||||
|
||||
ADDR_TYPE_UNIX = 0
|
||||
ADDR_TYPE_TCP = 1
|
||||
ADDR_TYPE_WS = 2
|
||||
|
||||
WEBSOCKETS_MIN_VERSION = (9, 1)
|
||||
# Need websockets 10 with python 3.10+
|
||||
if sys.version_info >= (3, 10, 0):
|
||||
WEBSOCKETS_MIN_VERSION = (10, 0)
|
||||
|
||||
|
||||
def parse_address(addr):
|
||||
if addr.startswith(UNIX_PREFIX):
|
||||
return (ADDR_TYPE_UNIX, (addr[len(UNIX_PREFIX) :],))
|
||||
elif addr.startswith(WS_PREFIX) or addr.startswith(WSS_PREFIX):
|
||||
return (ADDR_TYPE_WS, (addr,))
|
||||
else:
|
||||
m = re.match(r"\[(?P<host>[^\]]*)\]:(?P<port>\d+)$", addr)
|
||||
if m is not None:
|
||||
host = m.group("host")
|
||||
port = m.group("port")
|
||||
else:
|
||||
host, port = addr.split(":")
|
||||
|
||||
return (ADDR_TYPE_TCP, (host, int(port)))
|
||||
|
||||
|
||||
class AsyncClient(object):
|
||||
def __init__(
|
||||
self,
|
||||
proto_name,
|
||||
proto_version,
|
||||
logger,
|
||||
timeout=30,
|
||||
server_headers=False,
|
||||
headers={},
|
||||
):
|
||||
self.socket = None
|
||||
self.max_chunk = DEFAULT_MAX_CHUNK
|
||||
self.proto_name = proto_name
|
||||
self.proto_version = proto_version
|
||||
self.logger = logger
|
||||
self.timeout = timeout
|
||||
self.needs_server_headers = server_headers
|
||||
self.server_headers = {}
|
||||
self.headers = headers
|
||||
|
||||
async def connect_tcp(self, address, port):
|
||||
async def connect_sock():
|
||||
reader, writer = await asyncio.open_connection(address, port)
|
||||
return StreamConnection(reader, writer, self.timeout, self.max_chunk)
|
||||
|
||||
self._connect_sock = connect_sock
|
||||
|
||||
async def connect_unix(self, path):
|
||||
async def connect_sock():
|
||||
# AF_UNIX has path length issues so chdir here to workaround
|
||||
cwd = os.getcwd()
|
||||
try:
|
||||
os.chdir(os.path.dirname(path))
|
||||
# The socket must be opened synchronously so that CWD doesn't get
|
||||
# changed out from underneath us so we pass as a sock into asyncio
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
|
||||
sock.connect(os.path.basename(path))
|
||||
finally:
|
||||
os.chdir(cwd)
|
||||
reader, writer = await asyncio.open_unix_connection(sock=sock)
|
||||
return StreamConnection(reader, writer, self.timeout, self.max_chunk)
|
||||
|
||||
self._connect_sock = connect_sock
|
||||
|
||||
async def connect_websocket(self, uri):
|
||||
import websockets
|
||||
|
||||
try:
|
||||
version = tuple(
|
||||
int(v)
|
||||
for v in websockets.__version__.split(".")[
|
||||
0 : len(WEBSOCKETS_MIN_VERSION)
|
||||
]
|
||||
)
|
||||
except ValueError:
|
||||
raise ImportError(
|
||||
f"Unable to parse websockets version '{websockets.__version__}'"
|
||||
)
|
||||
|
||||
if version < WEBSOCKETS_MIN_VERSION:
|
||||
min_ver_str = ".".join(str(v) for v in WEBSOCKETS_MIN_VERSION)
|
||||
raise ImportError(
|
||||
f"Websockets version {websockets.__version__} is less than minimum required version {min_ver_str}"
|
||||
)
|
||||
|
||||
async def connect_sock():
|
||||
websocket = await websockets.connect(
|
||||
uri,
|
||||
ping_interval=None,
|
||||
open_timeout=self.timeout,
|
||||
)
|
||||
return WebsocketConnection(websocket, self.timeout)
|
||||
|
||||
self._connect_sock = connect_sock
|
||||
|
||||
async def setup_connection(self):
|
||||
# Send headers
|
||||
await self.socket.send("%s %s" % (self.proto_name, self.proto_version))
|
||||
await self.socket.send(
|
||||
"needs-headers: %s" % ("true" if self.needs_server_headers else "false")
|
||||
)
|
||||
for k, v in self.headers.items():
|
||||
await self.socket.send("%s: %s" % (k, v))
|
||||
|
||||
# End of headers
|
||||
await self.socket.send("")
|
||||
|
||||
self.server_headers = {}
|
||||
if self.needs_server_headers:
|
||||
while True:
|
||||
line = await self.socket.recv()
|
||||
if not line:
|
||||
# End headers
|
||||
break
|
||||
tag, value = line.split(":", 1)
|
||||
self.server_headers[tag.lower()] = value.strip()
|
||||
|
||||
async def get_header(self, tag, default):
|
||||
await self.connect()
|
||||
return self.server_headers.get(tag, default)
|
||||
|
||||
async def connect(self):
|
||||
if self.socket is None:
|
||||
self.socket = await self._connect_sock()
|
||||
await self.setup_connection()
|
||||
|
||||
async def disconnect(self):
|
||||
if self.socket is not None:
|
||||
await self.socket.close()
|
||||
self.socket = None
|
||||
|
||||
async def close(self):
|
||||
await self.disconnect()
|
||||
|
||||
async def _send_wrapper(self, proc):
|
||||
count = 0
|
||||
while True:
|
||||
try:
|
||||
await self.connect()
|
||||
return await proc()
|
||||
except (
|
||||
OSError,
|
||||
ConnectionError,
|
||||
ConnectionClosedError,
|
||||
json.JSONDecodeError,
|
||||
UnicodeDecodeError,
|
||||
) as e:
|
||||
self.logger.warning("Error talking to server: %s" % e)
|
||||
if count >= 3:
|
||||
if not isinstance(e, ConnectionError):
|
||||
raise ConnectionError(str(e))
|
||||
raise e
|
||||
await self.close()
|
||||
count += 1
|
||||
|
||||
def check_invoke_error(self, msg):
|
||||
if isinstance(msg, dict) and "invoke-error" in msg:
|
||||
raise InvokeError(msg["invoke-error"]["message"])
|
||||
|
||||
async def invoke(self, msg):
|
||||
async def proc():
|
||||
await self.socket.send_message(msg)
|
||||
return await self.socket.recv_message()
|
||||
|
||||
result = await self._send_wrapper(proc)
|
||||
self.check_invoke_error(result)
|
||||
return result
|
||||
|
||||
async def ping(self):
|
||||
return await self.invoke({"ping": {}})
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc_value, traceback):
|
||||
await self.close()
|
||||
|
||||
|
||||
class Client(object):
|
||||
def __init__(self):
|
||||
self.client = self._get_async_client()
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
# Override any pre-existing loop.
|
||||
# Without this, the PR server export selftest triggers a hang
|
||||
# when running with Python 3.7. The drawback is that there is
|
||||
# potential for issues if the PR and hash equiv (or some new)
|
||||
# clients need to both be instantiated in the same process.
|
||||
# This should be revisited if/when Python 3.9 becomes the
|
||||
# minimum required version for BitBake, as it seems not
|
||||
# required (but harmless) with it.
|
||||
asyncio.set_event_loop(self.loop)
|
||||
|
||||
self._add_methods("connect_tcp", "ping")
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_async_client(self):
|
||||
pass
|
||||
|
||||
def _get_downcall_wrapper(self, downcall):
|
||||
def wrapper(*args, **kwargs):
|
||||
return self.loop.run_until_complete(downcall(*args, **kwargs))
|
||||
|
||||
return wrapper
|
||||
|
||||
def _add_methods(self, *methods):
|
||||
for m in methods:
|
||||
downcall = getattr(self.client, m)
|
||||
setattr(self, m, self._get_downcall_wrapper(downcall))
|
||||
|
||||
def connect_unix(self, path):
|
||||
self.loop.run_until_complete(self.client.connect_unix(path))
|
||||
self.loop.run_until_complete(self.client.connect())
|
||||
|
||||
@property
|
||||
def max_chunk(self):
|
||||
return self.client.max_chunk
|
||||
|
||||
@max_chunk.setter
|
||||
def max_chunk(self, value):
|
||||
self.client.max_chunk = value
|
||||
|
||||
def disconnect(self):
|
||||
self.loop.run_until_complete(self.client.close())
|
||||
|
||||
def close(self):
|
||||
if self.loop:
|
||||
self.loop.run_until_complete(self.client.close())
|
||||
self.loop.run_until_complete(self.loop.shutdown_asyncgens())
|
||||
self.loop.close()
|
||||
self.loop = None
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.close()
|
||||
return False
|
||||
@@ -1,146 +0,0 @@
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
import asyncio
|
||||
import itertools
|
||||
import json
|
||||
from datetime import datetime
|
||||
from .exceptions import ClientError, ConnectionClosedError
|
||||
|
||||
|
||||
# The Python async server defaults to a 64K receive buffer, so we hardcode our
|
||||
# maximum chunk size. It would be better if the client and server reported to
|
||||
# each other what the maximum chunk sizes were, but that will slow down the
|
||||
# connection setup with a round trip delay so I'd rather not do that unless it
|
||||
# is necessary
|
||||
DEFAULT_MAX_CHUNK = 32 * 1024
|
||||
|
||||
|
||||
def chunkify(msg, max_chunk):
|
||||
if len(msg) < max_chunk - 1:
|
||||
yield "".join((msg, "\n"))
|
||||
else:
|
||||
yield "".join((json.dumps({"chunk-stream": None}), "\n"))
|
||||
|
||||
args = [iter(msg)] * (max_chunk - 1)
|
||||
for m in map("".join, itertools.zip_longest(*args, fillvalue="")):
|
||||
yield "".join(itertools.chain(m, "\n"))
|
||||
yield "\n"
|
||||
|
||||
|
||||
def json_serialize(obj):
|
||||
if isinstance(obj, datetime):
|
||||
return obj.isoformat()
|
||||
raise TypeError("Type %s not serializeable" % type(obj))
|
||||
|
||||
|
||||
class StreamConnection(object):
|
||||
def __init__(self, reader, writer, timeout, max_chunk=DEFAULT_MAX_CHUNK):
|
||||
self.reader = reader
|
||||
self.writer = writer
|
||||
self.timeout = timeout
|
||||
self.max_chunk = max_chunk
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self.writer.get_extra_info("peername")
|
||||
|
||||
async def send_message(self, msg):
|
||||
for c in chunkify(json.dumps(msg, default=json_serialize), self.max_chunk):
|
||||
self.writer.write(c.encode("utf-8"))
|
||||
await self.writer.drain()
|
||||
|
||||
async def recv_message(self):
|
||||
l = await self.recv()
|
||||
|
||||
m = json.loads(l)
|
||||
if not m:
|
||||
return m
|
||||
|
||||
if "chunk-stream" in m:
|
||||
lines = []
|
||||
while True:
|
||||
l = await self.recv()
|
||||
if not l:
|
||||
break
|
||||
lines.append(l)
|
||||
|
||||
m = json.loads("".join(lines))
|
||||
|
||||
return m
|
||||
|
||||
async def send(self, msg):
|
||||
self.writer.write(("%s\n" % msg).encode("utf-8"))
|
||||
await self.writer.drain()
|
||||
|
||||
async def recv(self):
|
||||
if self.timeout < 0:
|
||||
line = await self.reader.readline()
|
||||
else:
|
||||
try:
|
||||
line = await asyncio.wait_for(self.reader.readline(), self.timeout)
|
||||
except asyncio.TimeoutError:
|
||||
raise ConnectionError("Timed out waiting for data")
|
||||
|
||||
if not line:
|
||||
raise ConnectionClosedError("Connection closed")
|
||||
|
||||
line = line.decode("utf-8")
|
||||
|
||||
if not line.endswith("\n"):
|
||||
raise ConnectionError("Bad message %r" % (line))
|
||||
|
||||
return line.rstrip()
|
||||
|
||||
async def close(self):
|
||||
self.reader = None
|
||||
if self.writer is not None:
|
||||
self.writer.close()
|
||||
self.writer = None
|
||||
|
||||
|
||||
class WebsocketConnection(object):
|
||||
def __init__(self, socket, timeout):
|
||||
self.socket = socket
|
||||
self.timeout = timeout
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return ":".join(str(s) for s in self.socket.remote_address)
|
||||
|
||||
async def send_message(self, msg):
|
||||
await self.send(json.dumps(msg, default=json_serialize))
|
||||
|
||||
async def recv_message(self):
|
||||
m = await self.recv()
|
||||
return json.loads(m)
|
||||
|
||||
async def send(self, msg):
|
||||
import websockets.exceptions
|
||||
|
||||
try:
|
||||
await self.socket.send(msg)
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
raise ConnectionClosedError("Connection closed")
|
||||
|
||||
async def recv(self):
|
||||
import websockets.exceptions
|
||||
|
||||
try:
|
||||
if self.timeout < 0:
|
||||
return await self.socket.recv()
|
||||
|
||||
try:
|
||||
return await asyncio.wait_for(self.socket.recv(), self.timeout)
|
||||
except asyncio.TimeoutError:
|
||||
raise ConnectionError("Timed out waiting for data")
|
||||
except websockets.exceptions.ConnectionClosed:
|
||||
raise ConnectionClosedError("Connection closed")
|
||||
|
||||
async def close(self):
|
||||
if self.socket is not None:
|
||||
await self.socket.close()
|
||||
self.socket = None
|
||||
@@ -1,21 +0,0 @@
|
||||
#
|
||||
# Copyright BitBake Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
|
||||
|
||||
class ClientError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InvokeError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ServerError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ConnectionClosedError(Exception):
|
||||
pass
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user