mirror of
https://git.yoctoproject.org/poky
synced 2026-02-15 21:23:04 +01:00
Compare commits
339 Commits
1.3_M3.rc2
...
denzil-7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3456295898 | ||
|
|
c917351c9b | ||
|
|
f3db1cd8ff | ||
|
|
b0689417df | ||
|
|
270402dd38 | ||
|
|
5d30ffd8f8 | ||
|
|
c2c8bb40e8 | ||
|
|
625044e9a8 | ||
|
|
d571e5a68a | ||
|
|
8e078932c3 | ||
|
|
151d4fbc4e | ||
|
|
caa1d03089 | ||
|
|
a86e32a18b | ||
|
|
156c2554b7 | ||
|
|
b6037b6d2f | ||
|
|
cf77faba91 | ||
|
|
88b65c79ac | ||
|
|
bfae0622b5 | ||
|
|
01c1421270 | ||
|
|
2ccb03f9b7 | ||
|
|
07f304f4e2 | ||
|
|
db915496d3 | ||
|
|
8fe4344e74 | ||
|
|
3c57cb356e | ||
|
|
38d6972032 | ||
|
|
ef745cb34f | ||
|
|
a6f0dcbe7d | ||
|
|
cf796f8908 | ||
|
|
e416fb6920 | ||
|
|
aa66dc91d3 | ||
|
|
b45184aef3 | ||
|
|
0e43be806d | ||
|
|
d6935247dd | ||
|
|
b8f6d9cbfd | ||
|
|
2288ff099c | ||
|
|
93cc23571e | ||
|
|
95f2a5b635 | ||
|
|
75997b4565 | ||
|
|
970d279774 | ||
|
|
40e6fc6a65 | ||
|
|
e9c2218231 | ||
|
|
84399e189b | ||
|
|
846b7c3887 | ||
|
|
732007cbb6 | ||
|
|
9945923c8b | ||
|
|
9bf253f467 | ||
|
|
d156f75fea | ||
|
|
809d97b938 | ||
|
|
e5a85ac2e4 | ||
|
|
b4bb378261 | ||
|
|
e7d4eba0a9 | ||
|
|
aad5c9f699 | ||
|
|
42d9652fb1 | ||
|
|
4e09d164d9 | ||
|
|
d567e770c3 | ||
|
|
a5f5b1e80a | ||
|
|
d47234d4c9 | ||
|
|
3cdd930eeb | ||
|
|
cfd36177f7 | ||
|
|
1ecc27c20c | ||
|
|
82114edb4a | ||
|
|
a62752bb4f | ||
|
|
7ffad91e79 | ||
|
|
1e2d6bffc5 | ||
|
|
cb1c31939d | ||
|
|
bec76a3813 | ||
|
|
ead623b2a0 | ||
|
|
b973813796 | ||
|
|
8941d5aa3b | ||
|
|
f6876adb6a | ||
|
|
3c3614c562 | ||
|
|
1c71304f81 | ||
|
|
5be28549ae | ||
|
|
bbe83b55cd | ||
|
|
3c363a70aa | ||
|
|
2fab410f2e | ||
|
|
4b8d430c1f | ||
|
|
b0f05958fc | ||
|
|
57cdce3108 | ||
|
|
241653a01b | ||
|
|
f6fb4890df | ||
|
|
b4de44f425 | ||
|
|
b32c50e016 | ||
|
|
b5013e9e9e | ||
|
|
0cd0a3b475 | ||
|
|
825c647f65 | ||
|
|
16b6bc4288 | ||
|
|
4ef357f033 | ||
|
|
91714ea8ae | ||
|
|
fbb459aab9 | ||
|
|
7b7f3cff44 | ||
|
|
a512e68202 | ||
|
|
ef789c1327 | ||
|
|
2011408939 | ||
|
|
9520635a00 | ||
|
|
a259fdb296 | ||
|
|
55997cbf3d | ||
|
|
988318927a | ||
|
|
bf9a5226fc | ||
|
|
d72eea5a5d | ||
|
|
a99b03e3ed | ||
|
|
1773d1da62 | ||
|
|
d8ccc44114 | ||
|
|
6f3e6c75de | ||
|
|
89fa2c1fc6 | ||
|
|
e22b4411ae | ||
|
|
33921847a2 | ||
|
|
5427f5d70f | ||
|
|
4624b5eefb | ||
|
|
e7376bb459 | ||
|
|
c2bbe5f5d3 | ||
|
|
758677e212 | ||
|
|
b96bd8465a | ||
|
|
65ffa73950 | ||
|
|
a76fc366ce | ||
|
|
759237f721 | ||
|
|
3e632506c2 | ||
|
|
1b9306705c | ||
|
|
65706548f6 | ||
|
|
bc6b04fe22 | ||
|
|
8a51a8afe8 | ||
|
|
2517376ee8 | ||
|
|
9078e985ac | ||
|
|
b123553c1a | ||
|
|
717704d12c | ||
|
|
e5c5e20a5e | ||
|
|
96631f080b | ||
|
|
78d15a8015 | ||
|
|
ffff5fa2d7 | ||
|
|
119b7ff164 | ||
|
|
1162729c79 | ||
|
|
4591963649 | ||
|
|
3f30bf4eab | ||
|
|
ea032bb2c3 | ||
|
|
4bfb54e0ba | ||
|
|
729b396b21 | ||
|
|
bdb918f808 | ||
|
|
e4f8c7f693 | ||
|
|
4539cf1936 | ||
|
|
6631752c25 | ||
|
|
75b7901f22 | ||
|
|
c520132cb8 | ||
|
|
a8d4eb449f | ||
|
|
4253c34000 | ||
|
|
1a70ddc4e8 | ||
|
|
6352d0a9a1 | ||
|
|
0a6f9a5f5a | ||
|
|
7c5318e1a0 | ||
|
|
88927f4f1f | ||
|
|
68888987ce | ||
|
|
3129f4ff0e | ||
|
|
09ae715bb1 | ||
|
|
c26cfe7738 | ||
|
|
81aac104fa | ||
|
|
bc754beb3a | ||
|
|
e20af93811 | ||
|
|
235667966c | ||
|
|
258bbaa1d2 | ||
|
|
f44faa8757 | ||
|
|
3cf5fc2272 | ||
|
|
ffd554d2ff | ||
|
|
4899d07aa7 | ||
|
|
0b71ac7a99 | ||
|
|
bdebedb6cf | ||
|
|
b2b365e8f0 | ||
|
|
738f163797 | ||
|
|
1ddd5378ec | ||
|
|
ebbd09e21d | ||
|
|
09c83947da | ||
|
|
8c6455b6db | ||
|
|
73cdebf60d | ||
|
|
6b06a4fa1b | ||
|
|
2dcbb48df9 | ||
|
|
fb2335fa2b | ||
|
|
e972d78009 | ||
|
|
91d6344765 | ||
|
|
a707b3269c | ||
|
|
0d3748ca5d | ||
|
|
5f2b526109 | ||
|
|
6bb0fdda40 | ||
|
|
5ad28e97e6 | ||
|
|
495ea21c8b | ||
|
|
94e3e894d0 | ||
|
|
8389decfe6 | ||
|
|
7412611252 | ||
|
|
026d502b2a | ||
|
|
e81f7c6152 | ||
|
|
119e1b7dc9 | ||
|
|
5b3a0eac61 | ||
|
|
4c4924ad1b | ||
|
|
9e6d1101b4 | ||
|
|
2bddf70a84 | ||
|
|
6698060d8e | ||
|
|
bd3cd64da3 | ||
|
|
c88f25ddb4 | ||
|
|
ef215694de | ||
|
|
71a6fb605a | ||
|
|
bfc8589048 | ||
|
|
6514e193ac | ||
|
|
44fb9daa81 | ||
|
|
309b2c090e | ||
|
|
67c7bc5e6c | ||
|
|
e06e502bbb | ||
|
|
89c0e81273 | ||
|
|
78a5471a29 | ||
|
|
b30a243f3f | ||
|
|
20657c1fa0 | ||
|
|
3029a08744 | ||
|
|
d376a4e8f1 | ||
|
|
0d0846e06f | ||
|
|
59ac33c77f | ||
|
|
3cb36a5ed9 | ||
|
|
75e32007ef | ||
|
|
d52e74cee9 | ||
|
|
f1630d3cd4 | ||
|
|
b7f1a8f870 | ||
|
|
015f117d85 | ||
|
|
b8338046ba | ||
|
|
7552ccd06c | ||
|
|
e24d5cc2cd | ||
|
|
1f2fc974df | ||
|
|
a473ba170d | ||
|
|
a5fe09c6aa | ||
|
|
2072256b05 | ||
|
|
b623203ac9 | ||
|
|
c7e4a6ae2c | ||
|
|
1628159028 | ||
|
|
b477f676e3 | ||
|
|
9d2534ab24 | ||
|
|
df815f20c8 | ||
|
|
b64eefe2bb | ||
|
|
4abd299bf0 | ||
|
|
30c3c8420e | ||
|
|
a74fb01b6b | ||
|
|
c003c04590 | ||
|
|
35cc0b023f | ||
|
|
c2826b50ce | ||
|
|
75225bcc84 | ||
|
|
d3204ddc12 | ||
|
|
7c7ac8548d | ||
|
|
bbf95cae4c | ||
|
|
3df821277d | ||
|
|
4f4685469a | ||
|
|
d1bc1191d6 | ||
|
|
5c507a2fd7 | ||
|
|
bf4740cf66 | ||
|
|
24ffb5c0b1 | ||
|
|
a92fed4fe5 | ||
|
|
a518e1e3b1 | ||
|
|
fc9716930a | ||
|
|
f99ced96cf | ||
|
|
d0f0d1b41d | ||
|
|
77203b75f5 | ||
|
|
a0f1aca7a0 | ||
|
|
b3de1f1140 | ||
|
|
6e93ac2581 | ||
|
|
c1bfbf7168 | ||
|
|
5a7d852a94 | ||
|
|
3bf8069100 | ||
|
|
cbd192a6c5 | ||
|
|
6d22ae627b | ||
|
|
49a58c65b6 | ||
|
|
06cde35657 | ||
|
|
196a62b50c | ||
|
|
8ddaa3ede8 | ||
|
|
52ccf5a9eb | ||
|
|
b2c9b25f97 | ||
|
|
5a1fb95a8d | ||
|
|
22b9983cc7 | ||
|
|
7f5e6a1959 | ||
|
|
01025ad2c4 | ||
|
|
71580376c9 | ||
|
|
0774a11505 | ||
|
|
4d2d5abd8b | ||
|
|
884034b256 | ||
|
|
ee98021efe | ||
|
|
f52747d7a2 | ||
|
|
1bf998fe41 | ||
|
|
1b3c00a34f | ||
|
|
b3f870297e | ||
|
|
93deb57c91 | ||
|
|
2883b754a1 | ||
|
|
86325bbc5d | ||
|
|
746d718f53 | ||
|
|
c498338197 | ||
|
|
ba554bd865 | ||
|
|
0dda5d88a5 | ||
|
|
06f44161f1 | ||
|
|
4b4a018466 | ||
|
|
caf6532b51 | ||
|
|
a81cb954bb | ||
|
|
0089bb9ad0 | ||
|
|
ce8d4157db | ||
|
|
66b18cb5cd | ||
|
|
bbf33914ea | ||
|
|
e1e12bfd0c | ||
|
|
bc7f18c61d | ||
|
|
89e2958475 | ||
|
|
943c6917e6 | ||
|
|
2b6e86beae | ||
|
|
42a9a50771 | ||
|
|
74c34c9d3c | ||
|
|
e9b8cf485c | ||
|
|
2863d953bd | ||
|
|
716bdd4bf5 | ||
|
|
dfecd3e3d7 | ||
|
|
142de43be2 | ||
|
|
752c707df3 | ||
|
|
d20a24310e | ||
|
|
8e04664ffd | ||
|
|
3ab5d73f0c | ||
|
|
33f048240d | ||
|
|
0bf04aa4ad | ||
|
|
612555e6fe | ||
|
|
35196ff703 | ||
|
|
0a48c697d7 | ||
|
|
7e56770a60 | ||
|
|
9a548f0ee4 | ||
|
|
946c650a47 | ||
|
|
f99c947c32 | ||
|
|
9ffbd2ef22 | ||
|
|
66625417b4 | ||
|
|
e95ce40abd | ||
|
|
4a83ebbee0 | ||
|
|
90705b36ad | ||
|
|
be5a5c7e7b | ||
|
|
64471e9340 | ||
|
|
4becd60e65 | ||
|
|
9fcfda78b9 | ||
|
|
8558c3e1f4 | ||
|
|
0bfb42dbb6 | ||
|
|
37b069ea5d | ||
|
|
6d7260e8f6 | ||
|
|
236bda9ed6 | ||
|
|
375835092c | ||
|
|
2c3d4f5bee | ||
|
|
45114a9df0 | ||
|
|
08290c6003 | ||
|
|
729e7f774c |
31
.gitignore
vendored
31
.gitignore
vendored
@@ -1,8 +1,11 @@
|
||||
bitbake
|
||||
*.pyc
|
||||
*.pyo
|
||||
/*.patch
|
||||
build*/
|
||||
build*/conf/local.conf
|
||||
build*/conf/bblayers.conf
|
||||
build*/downloads
|
||||
build*/tmp/
|
||||
build*/sstate-cache
|
||||
pyshtables.py
|
||||
pstage/
|
||||
scripts/oe-git-proxy-socks
|
||||
@@ -14,5 +17,25 @@ meta-*
|
||||
*.orig
|
||||
*.rej
|
||||
*~
|
||||
|
||||
|
||||
documentation/adt-manual/adt-manual.html
|
||||
documentation/adt-manual/adt-manual.pdf
|
||||
documentation/adt-manual/adt-manual.tgz
|
||||
documentation/dev-manual/dev-manual.html
|
||||
documentation/dev-manual/dev-manual.pdf
|
||||
documentation/dev-manual/dev-manual.tgz
|
||||
documentation/poky-ref-manual/poky-ref-manual.html
|
||||
documentation/poky-ref-manual/poky-ref-manual.pdf
|
||||
documentation/poky-ref-manual/poky-ref-manual.tgz
|
||||
documentation/poky-ref-manual/bsp-guide.html
|
||||
documentation/poky-ref-manual/bsp-guide.pdf
|
||||
documentation/bsp-guide/bsp-guide.html
|
||||
documentation/bsp-guide/bsp-guide.pdf
|
||||
documentation/bsp-guide/bsp-guide.tgz
|
||||
documentation/yocto-project-qs/yocto-project-qs.html
|
||||
documentation/yocto-project-qs/yocto-project-qs.tgz
|
||||
documentation/kernel-manual/kernel-manual.html
|
||||
documentation/kernel-manual/kernel-manual.tgz
|
||||
documentation/kernel-manual/kernel-manual.pdf
|
||||
documentation/mega-manual/mega-manual.html
|
||||
documentation/mega-manual/mega-manual.pdf
|
||||
documentation/mega-manual/mega-manual.tgz
|
||||
|
||||
2
README
2
README
@@ -18,7 +18,7 @@ e.g. for the hardware support. Poky is in turn a component of the Yocto Project.
|
||||
|
||||
The Yocto Project has extensive documentation about the system including a
|
||||
reference manual which can be found at:
|
||||
http://yoctoproject.org/documentation
|
||||
http://yoctoproject.org/community/documentation
|
||||
|
||||
OpenEmbedded-Core is a layer containing the core metadata for current versions
|
||||
of OpenEmbedded. It is distro-less (can build a functional image with
|
||||
|
||||
@@ -40,7 +40,7 @@ from bb import cooker
|
||||
from bb import ui
|
||||
from bb import server
|
||||
|
||||
__version__ = "1.15.3"
|
||||
__version__ = "1.15.2"
|
||||
logger = logging.getLogger("BitBake")
|
||||
|
||||
|
||||
@@ -56,11 +56,10 @@ class BBConfiguration(object):
|
||||
|
||||
|
||||
def get_ui(config):
|
||||
if not config.ui:
|
||||
# modify 'ui' attribute because it is also read by cooker
|
||||
config.ui = os.environ.get('BITBAKE_UI', 'knotty')
|
||||
|
||||
interface = config.ui
|
||||
if config.ui:
|
||||
interface = config.ui
|
||||
else:
|
||||
interface = 'knotty'
|
||||
|
||||
try:
|
||||
# Dynamically load the UI based on the ui name. Although we
|
||||
@@ -118,9 +117,6 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
parser.add_option("-c", "--cmd", help = "Specify task to execute. Note that this only executes the specified task for the providee and the packages it depends on, i.e. 'compile' does not implicitly call stage for the dependencies (IOW: use only if you know what you are doing). Depending on the base.bbclass a listtasks tasks is defined and will show available tasks",
|
||||
action = "store", dest = "cmd")
|
||||
|
||||
parser.add_option("-C", "--clear-stamp", help = "Invalidate the stamp for the specified cmd such as 'compile' and run the default task for the specified target(s)",
|
||||
action = "store", dest = "invalidate_stamp")
|
||||
|
||||
parser.add_option("-r", "--read", help = "read the specified file before bitbake.conf",
|
||||
action = "append", dest = "prefile", default = [])
|
||||
|
||||
@@ -148,7 +144,7 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
parser.add_option("-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
|
||||
action = "store_true", dest = "show_environment", default = False)
|
||||
|
||||
parser.add_option("-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax, and the pn-buildlist to show the build list",
|
||||
parser.add_option("-g", "--graphviz", help = "emit the dependency trees of the specified packages in the dot syntax",
|
||||
action = "store_true", dest = "dot_graph", default = False)
|
||||
|
||||
parser.add_option("-I", "--ignore-deps", help = """Assume these dependencies don't exist and are already provided (equivalent to ASSUME_PROVIDED). Useful to make dependency graphs more appealing""",
|
||||
|
||||
@@ -138,7 +138,7 @@ class Commands(cmd.Cmd):
|
||||
|
||||
|
||||
def do_show_overlayed(self, args):
|
||||
"""list overlayed recipes (where the same recipe exists in another layer)
|
||||
"""list overlayed recipes (where the same recipe exists in another layer that has a higher layer priority)
|
||||
|
||||
usage: show-overlayed [-f] [-s]
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# 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
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'lib'))
|
||||
|
||||
import unittest
|
||||
try:
|
||||
import bb
|
||||
except RuntimeError as exc:
|
||||
sys.exit(str(exc))
|
||||
|
||||
tests = ["bb.tests.codeparser",
|
||||
"bb.tests.cow",
|
||||
"bb.tests.data",
|
||||
"bb.tests.fetch",
|
||||
"bb.tests.utils"]
|
||||
|
||||
for t in tests:
|
||||
__import__(t)
|
||||
|
||||
unittest.main(argv=["bitbake-selftest"] + tests)
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2012 Wind River Systems, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname( \
|
||||
os.path.abspath(__file__))), 'lib'))
|
||||
try:
|
||||
import bb
|
||||
except RuntimeError as exc:
|
||||
sys.exit(str(exc))
|
||||
|
||||
import gtk
|
||||
import optparse
|
||||
import pygtk
|
||||
|
||||
from bb.ui.crumbs.hig import DeployImageDialog, ImageSelectionDialog, CrumbsMessageDialog
|
||||
from bb.ui.crumbs.hobwidget import HobAltButton, HobButton
|
||||
|
||||
# I put all the fs bitbake supported here. Need more test.
|
||||
DEPLOYABLE_IMAGE_TYPES = ["jffs2", "cramfs", "ext2", "ext3", "btrfs", "squashfs", "ubi", "vmdk"]
|
||||
Title = "USB Image Writer"
|
||||
|
||||
class DeployWindow(gtk.Window):
|
||||
def __init__(self, image_path=''):
|
||||
super(DeployWindow, self).__init__()
|
||||
|
||||
if len(image_path) > 0:
|
||||
valid = True
|
||||
if not os.path.exists(image_path):
|
||||
valid = False
|
||||
lbl = "<b>Invalid image file path: %s.</b>\nPress <b>Select Image</b> to select an image." % image_path
|
||||
else:
|
||||
image_path = os.path.abspath(image_path)
|
||||
extend_name = os.path.splitext(image_path)[1][1:]
|
||||
if extend_name not in DEPLOYABLE_IMAGE_TYPES:
|
||||
valid = False
|
||||
lbl = "<b>Undeployable imge type: %s</b>\nPress <b>Select Image</b> to select an image." % extend_name
|
||||
|
||||
if not valid:
|
||||
image_path = ''
|
||||
crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
crumbs_dialog.run()
|
||||
crumbs_dialog.destroy()
|
||||
|
||||
self.deploy_dialog = DeployImageDialog(Title, image_path, self,
|
||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR, None, standalone=True)
|
||||
close_button = self.deploy_dialog.add_button("Close", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(close_button)
|
||||
close_button.connect('clicked', gtk.main_quit)
|
||||
|
||||
write_button = self.deploy_dialog.add_button("Write USB image", gtk.RESPONSE_YES)
|
||||
HobAltButton.style_button(write_button)
|
||||
|
||||
self.deploy_dialog.connect('select_image_clicked', self.select_image_clicked_cb)
|
||||
self.deploy_dialog.connect('destroy', gtk.main_quit)
|
||||
response = self.deploy_dialog.show()
|
||||
|
||||
def select_image_clicked_cb(self, dialog):
|
||||
cwd = os.getcwd()
|
||||
dialog = ImageSelectionDialog(cwd, DEPLOYABLE_IMAGE_TYPES, Title, self, gtk.FILE_CHOOSER_ACTION_SAVE )
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Open", gtk.RESPONSE_YES)
|
||||
HobAltButton.style_button(button)
|
||||
response = dialog.run()
|
||||
|
||||
if response == gtk.RESPONSE_YES:
|
||||
if not dialog.image_names:
|
||||
lbl = "<b>No selections made</b>\nClicked the radio button to select a image."
|
||||
crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
crumbs_dialog.run()
|
||||
crumbs_dialog.destroy()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
# get the full path of image
|
||||
image_path = os.path.join(dialog.image_folder, dialog.image_names[0])
|
||||
self.deploy_dialog.set_image_text_buffer(image_path)
|
||||
self.deploy_dialog.set_image_path(image_path)
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def main():
|
||||
parser = optparse.OptionParser(
|
||||
usage = """%prog [-h] [image_file]
|
||||
|
||||
%prog writes bootable images to USB devices. You can
|
||||
provide the image file on the command line or select it using the GUI.""")
|
||||
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
image_file = args[1] if len(args) > 1 else ''
|
||||
dw = DeployWindow(image_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
gtk.main()
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc(3)
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# Copyright (C) 2012 Wind River Systems, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# 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 is used for dumping the bb_cache.dat, the output format is:
|
||||
# recipe_path PN PV PACKAGES
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
# For importing bb.cache
|
||||
sys.path.insert(0, os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), '../lib'))
|
||||
from bb.cache import CoreRecipeInfo
|
||||
|
||||
import cPickle as pickle
|
||||
|
||||
def main(argv=None):
|
||||
"""
|
||||
Get the mapping for the target recipe.
|
||||
"""
|
||||
if len(argv) != 1:
|
||||
print >>sys.stderr, "Error, need one argument!"
|
||||
return 2
|
||||
|
||||
cachefile = argv[0]
|
||||
|
||||
with open(cachefile, "rb") as cachefile:
|
||||
pickled = pickle.Unpickler(cachefile)
|
||||
while cachefile:
|
||||
try:
|
||||
key = pickled.load()
|
||||
val = pickled.load()
|
||||
except Exception:
|
||||
break
|
||||
if isinstance(val, CoreRecipeInfo) and (not val.skipped):
|
||||
pn = val.pn
|
||||
# Filter out the native recipes.
|
||||
if key.startswith('virtual:native:') or pn.endswith("-native"):
|
||||
continue
|
||||
|
||||
# 1.0 is the default version for a no PV recipe.
|
||||
if val.__dict__.has_key("pv"):
|
||||
pv = val.pv
|
||||
else:
|
||||
pv = "1.0"
|
||||
|
||||
print("%s %s %s %s" % (key, pn, pv, ' '.join(val.packages)))
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
|
||||
@@ -103,13 +103,7 @@ Show debug logging for the specified logging domains
|
||||
.TP
|
||||
.B \-P, \-\-profile
|
||||
profile the command and print a report
|
||||
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
bitbake uses the following environment variables to control its
|
||||
operation:
|
||||
.TP
|
||||
.B BITBAKE_UI
|
||||
The bitbake user interface; overridden by the \fB-u\fP commandline option.
|
||||
|
||||
.SH AUTHORS
|
||||
BitBake was written by
|
||||
|
||||
@@ -228,7 +228,7 @@ addtask printdate before do_build</screen></para>
|
||||
<para>'nostamp' - don't generate a stamp file for a task. This means the task is always rexecuted.</para>
|
||||
<para>'fakeroot' - this task needs to be run in a fakeroot environment, obtained by adding the variables in FAKEROOTENV to the environment.</para>
|
||||
<para>'umask' - the umask to run the task under.</para>
|
||||
<para> For the 'deptask', 'rdeptask', 'depends', 'rdepends' and 'recrdeptask' flags please see the dependencies section.</para>
|
||||
<para> For the 'deptask', 'rdeptask', 'recdeptask' and 'recrdeptask' flags please see the dependencies section.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
@@ -308,35 +308,37 @@ SRC_URI_append_1.0.7+ = "file://some_patch_which_the_new_versions_need.patch;pat
|
||||
</section>
|
||||
<section>
|
||||
<title>Dependency handling</title>
|
||||
<para>BitBake handles dependencies at the task level since to allow for efficient operation with multiple processed executing in parallel. A robust method of specifying task dependencies is therefore needed. </para>
|
||||
<para>BitBake 1.7.x onwards works with the metadata at the task level since this is optimal when dealing with multiple threads of execution. A robust method of specifing task dependencies is therefore needed. </para>
|
||||
<section>
|
||||
<title>Dependencies internal to the .bb file</title>
|
||||
<para>Where the dependencies are internal to a given .bb file, the dependencies are handled by the previously detailed addtask directive.</para>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Build Dependencies</title>
|
||||
<title>DEPENDS</title>
|
||||
<para>DEPENDS lists build time dependencies. The 'deptask' flag for tasks is used to signify the task of each item listed in DEPENDS which must have completed before that task can be executed.</para>
|
||||
<para><screen>do_configure[deptask] = "do_populate_staging"</screen></para>
|
||||
<para>means the do_populate_staging task of each item in DEPENDS must have completed before do_configure can execute.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Runtime Dependencies</title>
|
||||
<para>The PACKAGES variable lists runtime packages and each of these can have RDEPENDS and RRECOMMENDS runtime dependencies. The 'rdeptask' flag for tasks is used to signify the task of each item runtime dependency which must have completed before that task can be executed.</para>
|
||||
<title>RDEPENDS</title>
|
||||
<para>RDEPENDS lists runtime dependencies. The 'rdeptask' flag for tasks is used to signify the task of each item listed in RDEPENDS which must have completed before that task can be executed.</para>
|
||||
<para><screen>do_package_write[rdeptask] = "do_package"</screen></para>
|
||||
<para>means the do_package task of each item in RDEPENDS must have completed before do_package_write can execute.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Recursive Dependencies</title>
|
||||
<para>These are specified with the 'recrdeptask' flag which is used signify the task(s) of dependencies which must have completed before that task can be executed. It works by looking though the build and runtime dependencies of the current recipe as well as any inter-task dependencies the task has, then adding a dependency on the listed task. It will then recurse through the dependencies of those tasks and so on.</para>
|
||||
<para>It may be desireable to recurse not just through the dependencies of those tasks but through the build and runtime dependencies of dependent tasks too. If that is the case, the taskname itself should be referenced in the task list, e.g. do_a[recrdeptask] = "do_a do_b".</para>
|
||||
<title>Recursive DEPENDS</title>
|
||||
<para>These are specified with the 'recdeptask' flag and is used signify the task(s) of each DEPENDS which must have completed before that task can be executed. It applies recursively so the DEPENDS of each item in the original DEPENDS must be met and so on.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Recursive RDEPENDS</title>
|
||||
<para>These are specified with the 'recrdeptask' flag and is used signify the task(s) of each RDEPENDS which must have completed before that task can be executed. It applies recursively so the RDEPENDS of each item in the original RDEPENDS must be met and so on. It also runs all DEPENDS first.</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Inter task</title>
|
||||
<para>The 'depends' flag for tasks is a more generic form of which allows an interdependency on specific tasks rather than specifying the data in DEPENDS.</para>
|
||||
<para>The 'depends' flag for tasks is a more generic form of which allows an interdependency on specific tasks rather than specifying the data in DEPENDS or RDEPENDS.</para>
|
||||
<para><screen>do_patch[depends] = "quilt-native:do_populate_staging"</screen></para>
|
||||
<para>means the do_populate_staging task of the target quilt-native must have completed before the do_patch can execute.</para>
|
||||
<para>The 'rdepends' flag works in a similar way but takes targets in the runtime namespace instead of the build time dependency namespace.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
__version__ = "1.15.3"
|
||||
__version__ = "1.15.2"
|
||||
|
||||
import sys
|
||||
if sys.version_info < (2, 6, 0):
|
||||
|
||||
@@ -135,8 +135,7 @@ class LogTee(object):
|
||||
|
||||
def __repr__(self):
|
||||
return '<LogTee {0}>'.format(self.name)
|
||||
def flush(self):
|
||||
self.outfile.flush()
|
||||
|
||||
|
||||
def exec_func(func, d, dirs = None):
|
||||
"""Execute an BB 'function'"""
|
||||
@@ -175,19 +174,8 @@ def exec_func(func, d, dirs = None):
|
||||
lockfiles = None
|
||||
|
||||
tempdir = data.getVar('T', d, 1)
|
||||
|
||||
# or func allows items to be executed outside of the normal
|
||||
# task set, such as buildhistory
|
||||
task = data.getVar('BB_RUNTASK', d, 1) or func
|
||||
if task == func:
|
||||
taskfunc = task
|
||||
else:
|
||||
taskfunc = "%s.%s" % (task, func)
|
||||
|
||||
runfmt = data.getVar('BB_RUNFMT', d, 1) or "run.{func}.{pid}"
|
||||
runfn = runfmt.format(taskfunc=taskfunc, task=task, func=func, pid=os.getpid())
|
||||
runfile = os.path.join(tempdir, runfn)
|
||||
bb.utils.mkdirhier(os.path.dirname(runfile))
|
||||
bb.utils.mkdirhier(tempdir)
|
||||
runfile = os.path.join(tempdir, 'run.{0}.{1}'.format(func, os.getpid()))
|
||||
|
||||
with bb.utils.fileslocked(lockfiles):
|
||||
if ispython:
|
||||
@@ -218,8 +206,6 @@ def exec_func_python(func, d, runfile, cwd=None):
|
||||
olddir = None
|
||||
os.chdir(cwd)
|
||||
|
||||
bb.debug(2, "Executing python function %s" % func)
|
||||
|
||||
try:
|
||||
comp = utils.better_compile(code, func, bbfile)
|
||||
utils.better_exec(comp, {"d": d}, code, bbfile)
|
||||
@@ -229,15 +215,13 @@ def exec_func_python(func, d, runfile, cwd=None):
|
||||
|
||||
raise FuncFailed(func, None)
|
||||
finally:
|
||||
bb.debug(2, "Python function %s finished" % func)
|
||||
|
||||
if cwd and olddir:
|
||||
try:
|
||||
os.chdir(olddir)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def exec_func_shell(func, d, runfile, cwd=None):
|
||||
def exec_func_shell(function, d, runfile, cwd=None):
|
||||
"""Execute a shell function from the metadata
|
||||
|
||||
Note on directory behavior. The 'dirs' varflag should contain a list
|
||||
@@ -250,18 +234,18 @@ def exec_func_shell(func, d, runfile, cwd=None):
|
||||
|
||||
with open(runfile, 'w') as script:
|
||||
script.write('#!/bin/sh -e\n')
|
||||
data.emit_func(func, script, d)
|
||||
data.emit_func(function, script, d)
|
||||
|
||||
if bb.msg.loggerVerboseLogs:
|
||||
script.write("set -x\n")
|
||||
if cwd:
|
||||
script.write("cd %s\n" % cwd)
|
||||
script.write("%s\n" % func)
|
||||
script.write("%s\n" % function)
|
||||
|
||||
os.chmod(runfile, 0775)
|
||||
|
||||
cmd = runfile
|
||||
if d.getVarFlag(func, 'fakeroot'):
|
||||
if d.getVarFlag(function, 'fakeroot'):
|
||||
fakerootcmd = d.getVar('FAKEROOT', True)
|
||||
if fakerootcmd:
|
||||
cmd = [fakerootcmd, runfile]
|
||||
@@ -271,15 +255,11 @@ def exec_func_shell(func, d, runfile, cwd=None):
|
||||
else:
|
||||
logfile = sys.stdout
|
||||
|
||||
bb.debug(2, "Executing shell function %s" % func)
|
||||
|
||||
try:
|
||||
bb.process.run(cmd, shell=False, stdin=NULL, log=logfile)
|
||||
except bb.process.CmdError:
|
||||
logfn = d.getVar('BB_LOGFILE', True)
|
||||
raise FuncFailed(func, logfn)
|
||||
|
||||
bb.debug(2, "Shell function %s finished" % func)
|
||||
raise FuncFailed(function, logfn)
|
||||
|
||||
def _task_data(fn, task, d):
|
||||
localdata = data.createCopy(d)
|
||||
@@ -310,23 +290,8 @@ def _exec_task(fn, task, d, quieterr):
|
||||
bb.fatal("T variable not set, unable to build")
|
||||
|
||||
bb.utils.mkdirhier(tempdir)
|
||||
|
||||
# Determine the logfile to generate
|
||||
logfmt = localdata.getVar('BB_LOGFMT', True) or 'log.{task}.{pid}'
|
||||
logbase = logfmt.format(task=task, pid=os.getpid())
|
||||
|
||||
# Document the order of the tasks...
|
||||
logorder = os.path.join(tempdir, 'log.task_order')
|
||||
try:
|
||||
logorderfile = file(logorder, 'a')
|
||||
except OSError:
|
||||
logger.exception("Opening log file '%s'", logorder)
|
||||
pass
|
||||
logorderfile.write('{0} ({1}): {2}\n'.format(task, os.getpid(), logbase))
|
||||
logorderfile.close()
|
||||
|
||||
# Setup the courtesy link to the logfn
|
||||
loglink = os.path.join(tempdir, 'log.{0}'.format(task))
|
||||
logbase = 'log.{0}.{1}'.format(task, os.getpid())
|
||||
logfn = os.path.join(tempdir, logbase)
|
||||
if loglink:
|
||||
bb.utils.remove(loglink)
|
||||
@@ -349,7 +314,6 @@ def _exec_task(fn, task, d, quieterr):
|
||||
# Handle logfiles
|
||||
si = file('/dev/null', 'r')
|
||||
try:
|
||||
bb.utils.mkdirhier(os.path.dirname(logfn))
|
||||
logfile = file(logfn, 'w')
|
||||
except OSError:
|
||||
logger.exception("Opening log file '%s'", logfn)
|
||||
@@ -376,7 +340,6 @@ def _exec_task(fn, task, d, quieterr):
|
||||
bblogger.addHandler(errchk)
|
||||
|
||||
localdata.setVar('BB_LOGFILE', logfn)
|
||||
localdata.setVar('BB_RUNTASK', task)
|
||||
|
||||
event.fire(TaskStarted(task, localdata), localdata)
|
||||
try:
|
||||
@@ -544,7 +507,6 @@ def add_tasks(tasklist, d):
|
||||
deptask = data.expand(flags[name], d)
|
||||
task_deps[name][task] = deptask
|
||||
getTask('depends')
|
||||
getTask('rdepends')
|
||||
getTask('deptask')
|
||||
getTask('rdeptask')
|
||||
getTask('recrdeptask')
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# ex:ts=4:sw=4:sts=4:et
|
||||
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||
#
|
||||
# BitBake Cache implementation
|
||||
# BitBake 'Event' implementation
|
||||
#
|
||||
# Caching of bitbake variables before task execution
|
||||
|
||||
# Copyright (C) 2006 Richard Purdie
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
|
||||
# but small sections based on code from bin/bitbake:
|
||||
# Copyright (C) 2003, 2004 Chris Larson
|
||||
@@ -43,7 +42,7 @@ except ImportError:
|
||||
logger.info("Importing cPickle failed. "
|
||||
"Falling back to a very slow implementation.")
|
||||
|
||||
__cache_version__ = "144"
|
||||
__cache_version__ = "143"
|
||||
|
||||
def getCacheFile(path, filename, data_hash):
|
||||
return os.path.join(path, filename + "." + data_hash)
|
||||
@@ -76,13 +75,9 @@ class RecipeInfoCommon(object):
|
||||
for task in tasks)
|
||||
|
||||
@classmethod
|
||||
def flaglist(cls, flag, varlist, metadata, squash=False):
|
||||
out_dict = dict((var, metadata.getVarFlag(var, flag, True))
|
||||
def flaglist(cls, flag, varlist, metadata):
|
||||
return dict((var, metadata.getVarFlag(var, flag, True))
|
||||
for var in varlist)
|
||||
if squash:
|
||||
return dict((k,v) for (k,v) in out_dict.iteritems() if v)
|
||||
else:
|
||||
return out_dict
|
||||
|
||||
@classmethod
|
||||
def getvar(cls, var, metadata):
|
||||
@@ -132,7 +127,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
self.stamp = self.getvar('STAMP', metadata)
|
||||
self.stamp_base = self.flaglist('stamp-base', self.tasks, metadata)
|
||||
self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata)
|
||||
self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True)
|
||||
self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
|
||||
self.depends = self.depvar('DEPENDS', metadata)
|
||||
self.provides = self.depvar('PROVIDES', metadata)
|
||||
@@ -159,7 +153,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.stamp = {}
|
||||
cachedata.stamp_base = {}
|
||||
cachedata.stamp_extrainfo = {}
|
||||
cachedata.file_checksums = {}
|
||||
cachedata.fn_provides = {}
|
||||
cachedata.pn_provides = defaultdict(list)
|
||||
cachedata.all_depends = []
|
||||
@@ -191,7 +184,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.stamp[fn] = self.stamp
|
||||
cachedata.stamp_base[fn] = self.stamp_base
|
||||
cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo
|
||||
cachedata.file_checksums[fn] = self.file_checksums
|
||||
|
||||
provides = [self.pn]
|
||||
for provide in self.provides:
|
||||
@@ -711,115 +703,4 @@ class CacheData(object):
|
||||
for info in info_array:
|
||||
info.add_cacheData(self, fn)
|
||||
|
||||
|
||||
class MultiProcessCache(object):
|
||||
"""
|
||||
BitBake multi-process cache implementation
|
||||
|
||||
Used by the codeparser & file checksum caches
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.cachefile = None
|
||||
self.cachedata = self.create_cachedata()
|
||||
self.cachedata_extras = self.create_cachedata()
|
||||
|
||||
def init_cache(self, d):
|
||||
cachedir = (d.getVar("PERSISTENT_DIR", True) or
|
||||
d.getVar("CACHE", True))
|
||||
if cachedir in [None, '']:
|
||||
return
|
||||
bb.utils.mkdirhier(cachedir)
|
||||
self.cachefile = os.path.join(cachedir, self.__class__.cache_file_name)
|
||||
logger.debug(1, "Using cache in '%s'", self.cachefile)
|
||||
|
||||
try:
|
||||
p = pickle.Unpickler(file(self.cachefile, "rb"))
|
||||
data, version = p.load()
|
||||
except:
|
||||
return
|
||||
|
||||
if version != self.__class__.CACHE_VERSION:
|
||||
return
|
||||
|
||||
self.cachedata = data
|
||||
|
||||
def internSet(self, items):
|
||||
new = set()
|
||||
for i in items:
|
||||
new.add(intern(i))
|
||||
return new
|
||||
|
||||
def compress_keys(self, data):
|
||||
# Override in subclasses if desired
|
||||
return
|
||||
|
||||
def create_cachedata(self):
|
||||
data = [{}]
|
||||
return data
|
||||
|
||||
def save_extras(self, d):
|
||||
if not self.cachefile:
|
||||
return
|
||||
|
||||
glf = bb.utils.lockfile(self.cachefile + ".lock", shared=True)
|
||||
|
||||
i = os.getpid()
|
||||
lf = None
|
||||
while not lf:
|
||||
lf = bb.utils.lockfile(self.cachefile + ".lock." + str(i), retry=False)
|
||||
if not lf or os.path.exists(self.cachefile + "-" + str(i)):
|
||||
if lf:
|
||||
bb.utils.unlockfile(lf)
|
||||
lf = None
|
||||
i = i + 1
|
||||
continue
|
||||
|
||||
p = pickle.Pickler(file(self.cachefile + "-" + str(i), "wb"), -1)
|
||||
p.dump([self.cachedata_extras, self.__class__.CACHE_VERSION])
|
||||
|
||||
bb.utils.unlockfile(lf)
|
||||
bb.utils.unlockfile(glf)
|
||||
|
||||
def merge_data(self, source, dest):
|
||||
for j in range(0,len(dest)):
|
||||
for h in source[j]:
|
||||
if h not in dest[j]:
|
||||
dest[j][h] = source[j][h]
|
||||
|
||||
def save_merge(self, d):
|
||||
if not self.cachefile:
|
||||
return
|
||||
|
||||
glf = bb.utils.lockfile(self.cachefile + ".lock")
|
||||
|
||||
try:
|
||||
p = pickle.Unpickler(file(self.cachefile, "rb"))
|
||||
data, version = p.load()
|
||||
except (IOError, EOFError):
|
||||
data, version = None, None
|
||||
|
||||
if version != self.__class__.CACHE_VERSION:
|
||||
data = self.create_cachedata()
|
||||
|
||||
for f in [y for y in os.listdir(os.path.dirname(self.cachefile)) if y.startswith(os.path.basename(self.cachefile) + '-')]:
|
||||
f = os.path.join(os.path.dirname(self.cachefile), f)
|
||||
try:
|
||||
p = pickle.Unpickler(file(f, "rb"))
|
||||
extradata, version = p.load()
|
||||
except (IOError, EOFError):
|
||||
extradata, version = self.create_cachedata(), None
|
||||
|
||||
if version != self.__class__.CACHE_VERSION:
|
||||
continue
|
||||
|
||||
self.merge_data(extradata, data)
|
||||
os.unlink(f)
|
||||
|
||||
self.compress_keys(data)
|
||||
|
||||
p = pickle.Pickler(file(self.cachefile, "wb"), -1)
|
||||
p.dump([data, self.__class__.CACHE_VERSION])
|
||||
|
||||
bb.utils.unlockfile(glf)
|
||||
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
# Local file checksum cache implementation
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import os
|
||||
import stat
|
||||
import bb.utils
|
||||
import logging
|
||||
from bb.cache import MultiProcessCache
|
||||
|
||||
logger = logging.getLogger("BitBake.Cache")
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
logger.info("Importing cPickle failed. "
|
||||
"Falling back to a very slow implementation.")
|
||||
|
||||
|
||||
# mtime cache (non-persistent)
|
||||
# based upon the assumption that files do not change during bitbake run
|
||||
class FileMtimeCache(object):
|
||||
cache = {}
|
||||
|
||||
def cached_mtime(self, f):
|
||||
if f not in self.cache:
|
||||
self.cache[f] = os.stat(f)[stat.ST_MTIME]
|
||||
return self.cache[f]
|
||||
|
||||
def cached_mtime_noerror(self, f):
|
||||
if f not in self.cache:
|
||||
try:
|
||||
self.cache[f] = os.stat(f)[stat.ST_MTIME]
|
||||
except OSError:
|
||||
return 0
|
||||
return self.cache[f]
|
||||
|
||||
def update_mtime(self, f):
|
||||
self.cache[f] = os.stat(f)[stat.ST_MTIME]
|
||||
return self.cache[f]
|
||||
|
||||
def clear(self):
|
||||
self.cache.clear()
|
||||
|
||||
# Checksum + mtime cache (persistent)
|
||||
class FileChecksumCache(MultiProcessCache):
|
||||
cache_file_name = "local_file_checksum_cache.dat"
|
||||
CACHE_VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
self.mtime_cache = FileMtimeCache()
|
||||
MultiProcessCache.__init__(self)
|
||||
|
||||
def get_checksum(self, f):
|
||||
entry = self.cachedata[0].get(f)
|
||||
cmtime = self.mtime_cache.cached_mtime(f)
|
||||
if entry:
|
||||
(mtime, hashval) = entry
|
||||
if cmtime == mtime:
|
||||
return hashval
|
||||
else:
|
||||
bb.debug(2, "file %s changed mtime, recompute checksum" % f)
|
||||
|
||||
hashval = bb.utils.md5_file(f)
|
||||
self.cachedata_extras[0][f] = (cmtime, hashval)
|
||||
return hashval
|
||||
|
||||
def merge_data(self, source, dest):
|
||||
for h in source[0]:
|
||||
if h in dest:
|
||||
(smtime, _) = source[0][h]
|
||||
(dmtime, _) = dest[0][h]
|
||||
if smtime > dmtime:
|
||||
dest[0][h] = source[0][h]
|
||||
else:
|
||||
dest[0][h] = source[0][h]
|
||||
@@ -5,10 +5,10 @@ import os.path
|
||||
import bb.utils, bb.data
|
||||
from itertools import chain
|
||||
from pysh import pyshyacc, pyshlex, sherrors
|
||||
from bb.cache import MultiProcessCache
|
||||
|
||||
|
||||
logger = logging.getLogger('BitBake.CodeParser')
|
||||
PARSERCACHE_VERSION = 2
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
@@ -32,56 +32,133 @@ def check_indent(codestr):
|
||||
|
||||
return codestr
|
||||
|
||||
pythonparsecache = {}
|
||||
shellparsecache = {}
|
||||
pythonparsecacheextras = {}
|
||||
shellparsecacheextras = {}
|
||||
|
||||
class CodeParserCache(MultiProcessCache):
|
||||
cache_file_name = "bb_codeparser.dat"
|
||||
CACHE_VERSION = 2
|
||||
|
||||
def __init__(self):
|
||||
MultiProcessCache.__init__(self)
|
||||
self.pythoncache = self.cachedata[0]
|
||||
self.shellcache = self.cachedata[1]
|
||||
self.pythoncacheextras = self.cachedata_extras[0]
|
||||
self.shellcacheextras = self.cachedata_extras[1]
|
||||
|
||||
def init_cache(self, d):
|
||||
MultiProcessCache.init_cache(self, d)
|
||||
|
||||
# cachedata gets re-assigned in the parent
|
||||
self.pythoncache = self.cachedata[0]
|
||||
self.shellcache = self.cachedata[1]
|
||||
|
||||
def compress_keys(self, data):
|
||||
# When the dicts are originally created, python calls intern() on the set keys
|
||||
# which significantly improves memory usage. Sadly the pickle/unpickle process
|
||||
# doesn't call intern() on the keys and results in the same strings being duplicated
|
||||
# in memory. This also means pickle will save the same string multiple times in
|
||||
# the cache file. By interning the data here, the cache file shrinks dramatically
|
||||
# meaning faster load times and the reloaded cache files also consume much less
|
||||
# memory. This is worth any performance hit from this loops and the use of the
|
||||
# intern() data storage.
|
||||
# Python 3.x may behave better in this area
|
||||
for h in data[0]:
|
||||
data[0][h]["refs"] = self.internSet(data[0][h]["refs"])
|
||||
data[0][h]["execs"] = self.internSet(data[0][h]["execs"])
|
||||
for h in data[1]:
|
||||
data[1][h]["execs"] = self.internSet(data[1][h]["execs"])
|
||||
return
|
||||
|
||||
def create_cachedata(self):
|
||||
data = [{}, {}]
|
||||
return data
|
||||
|
||||
codeparsercache = CodeParserCache()
|
||||
def parser_cachefile(d):
|
||||
cachedir = (d.getVar("PERSISTENT_DIR", True) or
|
||||
d.getVar("CACHE", True))
|
||||
if cachedir in [None, '']:
|
||||
return None
|
||||
bb.utils.mkdirhier(cachedir)
|
||||
cachefile = os.path.join(cachedir, "bb_codeparser.dat")
|
||||
logger.debug(1, "Using cache in '%s' for codeparser cache", cachefile)
|
||||
return cachefile
|
||||
|
||||
def parser_cache_init(d):
|
||||
codeparsercache.init_cache(d)
|
||||
global pythonparsecache
|
||||
global shellparsecache
|
||||
|
||||
cachefile = parser_cachefile(d)
|
||||
if not cachefile:
|
||||
return
|
||||
|
||||
try:
|
||||
p = pickle.Unpickler(file(cachefile, "rb"))
|
||||
data, version = p.load()
|
||||
except:
|
||||
return
|
||||
|
||||
if version != PARSERCACHE_VERSION:
|
||||
return
|
||||
|
||||
pythonparsecache = data[0]
|
||||
shellparsecache = data[1]
|
||||
|
||||
def parser_cache_save(d):
|
||||
codeparsercache.save_extras(d)
|
||||
cachefile = parser_cachefile(d)
|
||||
if not cachefile:
|
||||
return
|
||||
|
||||
glf = bb.utils.lockfile(cachefile + ".lock", shared=True)
|
||||
|
||||
i = os.getpid()
|
||||
lf = None
|
||||
while not lf:
|
||||
shellcache = {}
|
||||
pythoncache = {}
|
||||
|
||||
lf = bb.utils.lockfile(cachefile + ".lock." + str(i), retry=False)
|
||||
if not lf or os.path.exists(cachefile + "-" + str(i)):
|
||||
if lf:
|
||||
bb.utils.unlockfile(lf)
|
||||
lf = None
|
||||
i = i + 1
|
||||
continue
|
||||
|
||||
shellcache = shellparsecacheextras
|
||||
pythoncache = pythonparsecacheextras
|
||||
|
||||
p = pickle.Pickler(file(cachefile + "-" + str(i), "wb"), -1)
|
||||
p.dump([[pythoncache, shellcache], PARSERCACHE_VERSION])
|
||||
|
||||
bb.utils.unlockfile(lf)
|
||||
bb.utils.unlockfile(glf)
|
||||
|
||||
def internSet(items):
|
||||
new = set()
|
||||
for i in items:
|
||||
new.add(intern(i))
|
||||
return new
|
||||
|
||||
def parser_cache_savemerge(d):
|
||||
codeparsercache.save_merge(d)
|
||||
cachefile = parser_cachefile(d)
|
||||
if not cachefile:
|
||||
return
|
||||
|
||||
glf = bb.utils.lockfile(cachefile + ".lock")
|
||||
|
||||
try:
|
||||
p = pickle.Unpickler(file(cachefile, "rb"))
|
||||
data, version = p.load()
|
||||
except (IOError, EOFError):
|
||||
data, version = None, None
|
||||
|
||||
if version != PARSERCACHE_VERSION:
|
||||
data = [{}, {}]
|
||||
|
||||
for f in [y for y in os.listdir(os.path.dirname(cachefile)) if y.startswith(os.path.basename(cachefile) + '-')]:
|
||||
f = os.path.join(os.path.dirname(cachefile), f)
|
||||
try:
|
||||
p = pickle.Unpickler(file(f, "rb"))
|
||||
extradata, version = p.load()
|
||||
except (IOError, EOFError):
|
||||
extradata, version = [{}, {}], None
|
||||
|
||||
if version != PARSERCACHE_VERSION:
|
||||
continue
|
||||
|
||||
for h in extradata[0]:
|
||||
if h not in data[0]:
|
||||
data[0][h] = extradata[0][h]
|
||||
for h in extradata[1]:
|
||||
if h not in data[1]:
|
||||
data[1][h] = extradata[1][h]
|
||||
os.unlink(f)
|
||||
|
||||
# When the dicts are originally created, python calls intern() on the set keys
|
||||
# which significantly improves memory usage. Sadly the pickle/unpickle process
|
||||
# doesn't call intern() on the keys and results in the same strings being duplicated
|
||||
# in memory. This also means pickle will save the same string multiple times in
|
||||
# the cache file. By interning the data here, the cache file shrinks dramatically
|
||||
# meaning faster load times and the reloaded cache files also consume much less
|
||||
# memory. This is worth any performance hit from this loops and the use of the
|
||||
# intern() data storage.
|
||||
# Python 3.x may behave better in this area
|
||||
for h in data[0]:
|
||||
data[0][h]["refs"] = internSet(data[0][h]["refs"])
|
||||
data[0][h]["execs"] = internSet(data[0][h]["execs"])
|
||||
for h in data[1]:
|
||||
data[1][h]["execs"] = internSet(data[1][h]["execs"])
|
||||
|
||||
p = pickle.Pickler(file(cachefile, "wb"), -1)
|
||||
p.dump([data, PARSERCACHE_VERSION])
|
||||
|
||||
bb.utils.unlockfile(glf)
|
||||
|
||||
|
||||
Logger = logging.getLoggerClass()
|
||||
class BufferedLogger(Logger):
|
||||
@@ -158,14 +235,14 @@ class PythonParser():
|
||||
def parse_python(self, node):
|
||||
h = hash(str(node))
|
||||
|
||||
if h in codeparsercache.pythoncache:
|
||||
self.references = codeparsercache.pythoncache[h]["refs"]
|
||||
self.execs = codeparsercache.pythoncache[h]["execs"]
|
||||
if h in pythonparsecache:
|
||||
self.references = pythonparsecache[h]["refs"]
|
||||
self.execs = pythonparsecache[h]["execs"]
|
||||
return
|
||||
|
||||
if h in codeparsercache.pythoncacheextras:
|
||||
self.references = codeparsercache.pythoncacheextras[h]["refs"]
|
||||
self.execs = codeparsercache.pythoncacheextras[h]["execs"]
|
||||
if h in pythonparsecacheextras:
|
||||
self.references = pythonparsecacheextras[h]["refs"]
|
||||
self.execs = pythonparsecacheextras[h]["execs"]
|
||||
return
|
||||
|
||||
|
||||
@@ -179,9 +256,9 @@ class PythonParser():
|
||||
self.references.update(self.var_references)
|
||||
self.references.update(self.var_execs)
|
||||
|
||||
codeparsercache.pythoncacheextras[h] = {}
|
||||
codeparsercache.pythoncacheextras[h]["refs"] = self.references
|
||||
codeparsercache.pythoncacheextras[h]["execs"] = self.execs
|
||||
pythonparsecacheextras[h] = {}
|
||||
pythonparsecacheextras[h]["refs"] = self.references
|
||||
pythonparsecacheextras[h]["execs"] = self.execs
|
||||
|
||||
class ShellParser():
|
||||
def __init__(self, name, log):
|
||||
@@ -199,12 +276,12 @@ class ShellParser():
|
||||
|
||||
h = hash(str(value))
|
||||
|
||||
if h in codeparsercache.shellcache:
|
||||
self.execs = codeparsercache.shellcache[h]["execs"]
|
||||
if h in shellparsecache:
|
||||
self.execs = shellparsecache[h]["execs"]
|
||||
return self.execs
|
||||
|
||||
if h in codeparsercache.shellcacheextras:
|
||||
self.execs = codeparsercache.shellcacheextras[h]["execs"]
|
||||
if h in shellparsecacheextras:
|
||||
self.execs = shellparsecacheextras[h]["execs"]
|
||||
return self.execs
|
||||
|
||||
try:
|
||||
@@ -216,8 +293,8 @@ class ShellParser():
|
||||
self.process_tokens(token)
|
||||
self.execs = set(cmd for cmd in self.allexecs if cmd not in self.funcdefs)
|
||||
|
||||
codeparsercache.shellcacheextras[h] = {}
|
||||
codeparsercache.shellcacheextras[h]["execs"] = self.execs
|
||||
shellparsecacheextras[h] = {}
|
||||
shellparsecacheextras[h]["execs"] = self.execs
|
||||
|
||||
return self.execs
|
||||
|
||||
|
||||
@@ -158,7 +158,6 @@ class BBCooker:
|
||||
#
|
||||
self.configuration.event_data = bb.data.createCopy(self.configuration.data)
|
||||
bb.data.update_data(self.configuration.event_data)
|
||||
bb.parse.init_parser(self.configuration.event_data)
|
||||
|
||||
# TOSTOP must not be set or our children will hang when they output
|
||||
fd = sys.stdout.fileno()
|
||||
@@ -535,15 +534,11 @@ class BBCooker:
|
||||
|
||||
# Prints a flattened form of package-depends below where subpackages of a package are merged into the main pn
|
||||
depends_file = file('pn-depends.dot', 'w' )
|
||||
buildlist_file = file('pn-buildlist', 'w' )
|
||||
print("digraph depends {", file=depends_file)
|
||||
for pn in depgraph["pn"]:
|
||||
fn = depgraph["pn"][pn]["filename"]
|
||||
version = depgraph["pn"][pn]["version"]
|
||||
print('"%s" [label="%s %s\\n%s"]' % (pn, pn, version, fn), file=depends_file)
|
||||
print("%s" % pn, file=buildlist_file)
|
||||
buildlist_file.close()
|
||||
logger.info("PN build list saved to 'pn-buildlist'")
|
||||
for pn in depgraph["depends"]:
|
||||
for depend in depgraph["depends"][pn]:
|
||||
print('"%s" -> "%s"' % (pn, depend), file=depends_file)
|
||||
@@ -990,12 +985,12 @@ class BBCooker:
|
||||
"""
|
||||
Find the .bb files which match the expression in 'buildfile'.
|
||||
"""
|
||||
|
||||
if bf.startswith("/") or bf.startswith("../"):
|
||||
bf = os.path.abspath(bf)
|
||||
filelist, masked = self.collect_bbfiles()
|
||||
try:
|
||||
os.stat(bf)
|
||||
bf = os.path.abspath(bf)
|
||||
return [bf]
|
||||
except OSError:
|
||||
regexp = re.compile(bf)
|
||||
@@ -1206,9 +1201,8 @@ class BBCooker:
|
||||
|
||||
if not self.parser.parse_next():
|
||||
collectlog.debug(1, "parsing complete")
|
||||
if not self.parser.error:
|
||||
self.show_appends_with_no_recipes()
|
||||
self.buildDepgraph()
|
||||
self.show_appends_with_no_recipes()
|
||||
self.buildDepgraph()
|
||||
self.state = state.running
|
||||
return None
|
||||
|
||||
@@ -1576,7 +1570,6 @@ class CookerParser(object):
|
||||
def init():
|
||||
Parser.cfg = self.cfgdata
|
||||
multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cfgdata,), exitpriority=1)
|
||||
multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, args=(self.cfgdata,), exitpriority=1)
|
||||
|
||||
self.feeder_quit = multiprocessing.Queue(maxsize=1)
|
||||
self.parser_quit = multiprocessing.Queue(maxsize=self.num_processes)
|
||||
@@ -1603,7 +1596,6 @@ class CookerParser(object):
|
||||
self.skipped, self.masked,
|
||||
self.virtuals, self.error,
|
||||
self.total)
|
||||
|
||||
bb.event.fire(event, self.cfgdata)
|
||||
self.feeder_quit.put(None)
|
||||
for process in self.processes:
|
||||
@@ -1629,7 +1621,6 @@ class CookerParser(object):
|
||||
sync.start()
|
||||
multiprocessing.util.Finalize(None, sync.join, exitpriority=-100)
|
||||
bb.codeparser.parser_cache_savemerge(self.cooker.configuration.data)
|
||||
bb.fetch.fetcher_parse_done(self.cooker.configuration.data)
|
||||
|
||||
def load_cached(self):
|
||||
for filename, appends in self.fromcache:
|
||||
@@ -1661,25 +1652,16 @@ class CookerParser(object):
|
||||
self.shutdown()
|
||||
return False
|
||||
except ParsingFailure as exc:
|
||||
self.error += 1
|
||||
logger.error('Unable to parse %s: %s' %
|
||||
(exc.recipe, bb.exceptions.to_string(exc.realexception)))
|
||||
self.shutdown(clean=False)
|
||||
except bb.parse.ParseError as exc:
|
||||
self.error += 1
|
||||
except (bb.parse.ParseError, bb.data_smart.ExpansionError) as exc:
|
||||
logger.error(str(exc))
|
||||
self.shutdown(clean=False)
|
||||
except bb.data_smart.ExpansionError as exc:
|
||||
self.error += 1
|
||||
_, value, _ = sys.exc_info()
|
||||
logger.error('ExpansionError during parsing %s: %s', value.recipe, str(exc))
|
||||
self.shutdown(clean=False)
|
||||
except SyntaxError as exc:
|
||||
self.error += 1
|
||||
logger.error('Unable to parse %s', exc.recipe)
|
||||
self.shutdown(clean=False)
|
||||
except Exception as exc:
|
||||
self.error += 1
|
||||
etype, value, tb = sys.exc_info()
|
||||
logger.error('Unable to parse %s', value.recipe,
|
||||
exc_info=(etype, value, exc.traceback))
|
||||
|
||||
@@ -279,20 +279,13 @@ def build_dependencies(key, keys, shelldeps, vardepvals, d):
|
||||
deps = set()
|
||||
vardeps = d.getVarFlag(key, "vardeps", True)
|
||||
try:
|
||||
if key[-1] == ']':
|
||||
vf = key[:-1].split('[')
|
||||
value = d.getVarFlag(vf[0], vf[1], False)
|
||||
else:
|
||||
value = d.getVar(key, False)
|
||||
|
||||
value = d.getVar(key, False)
|
||||
if key in vardepvals:
|
||||
value = d.getVarFlag(key, "vardepvalue", True)
|
||||
elif d.getVarFlag(key, "func"):
|
||||
if d.getVarFlag(key, "python"):
|
||||
parsedvar = d.expandWithRefs(value, key)
|
||||
parser = bb.codeparser.PythonParser(key, logger)
|
||||
if parsedvar.value and "\t" in parsedvar.value:
|
||||
logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
|
||||
parser.parse_python(parsedvar.value)
|
||||
deps = deps | parser.references
|
||||
else:
|
||||
@@ -308,19 +301,6 @@ def build_dependencies(key, keys, shelldeps, vardepvals, d):
|
||||
parser = d.expandWithRefs(value, key)
|
||||
deps |= parser.references
|
||||
deps = deps | (keys & parser.execs)
|
||||
|
||||
# Add varflags, assuming an exclusion list is set
|
||||
varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS', True)
|
||||
if varflagsexcl:
|
||||
varfdeps = []
|
||||
varflags = d.getVarFlags(key)
|
||||
if varflags:
|
||||
for f in varflags:
|
||||
if f not in varflagsexcl:
|
||||
varfdeps.append('%s[%s]' % (key, f))
|
||||
if varfdeps:
|
||||
deps |= set(varfdeps)
|
||||
|
||||
deps |= set((vardeps or "").split())
|
||||
deps -= set((d.getVarFlag(key, "vardepsexclude", True) or "").split())
|
||||
except:
|
||||
|
||||
@@ -39,7 +39,7 @@ from bb.COW import COWDictBase
|
||||
logger = logging.getLogger("BitBake.Data")
|
||||
|
||||
__setvar_keyword__ = ["_append", "_prepend"]
|
||||
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?$')
|
||||
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend)(_(?P<add>.*))?')
|
||||
__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
|
||||
__expand_python_regexp__ = re.compile(r"\${@.+?}")
|
||||
|
||||
@@ -102,10 +102,7 @@ class ExpansionError(Exception):
|
||||
self.expression = expression
|
||||
self.variablename = varname
|
||||
self.exception = exception
|
||||
if varname:
|
||||
self.msg = "Failure expanding variable %s, expression was %s which triggered exception %s: %s" % (varname, expression, type(exception).__name__, exception)
|
||||
else:
|
||||
self.msg = "Failure expanding expression %s which triggered exception %s: %s" % (expression, type(exception).__name__, exception)
|
||||
self.msg = "Failure expanding variable %s, expression was %s which triggered exception %s: %s" % (varname, expression, type(exception).__name__, exception)
|
||||
Exception.__init__(self, self.msg)
|
||||
self.args = (varname, expression, exception)
|
||||
def __str__(self):
|
||||
@@ -198,12 +195,7 @@ class DataSmart(MutableMapping):
|
||||
for append in appends:
|
||||
keep = []
|
||||
for (a, o) in self.getVarFlag(append, op) or []:
|
||||
match = True
|
||||
if o:
|
||||
for o2 in o.split("_"):
|
||||
if not o2 in overrides:
|
||||
match = False
|
||||
if not match:
|
||||
if o and not o in overrides:
|
||||
keep.append((a ,o))
|
||||
continue
|
||||
|
||||
|
||||
@@ -312,14 +312,6 @@ class BuildCompleted(BuildBase, OperationCompleted):
|
||||
OperationCompleted.__init__(self, total, "Building Failed")
|
||||
BuildBase.__init__(self, n, p, failures)
|
||||
|
||||
class DiskFull(Event):
|
||||
"""Disk full case build aborted"""
|
||||
def __init__(self, dev, type, freespace, mountpoint):
|
||||
Event.__init__(self)
|
||||
self._dev = dev
|
||||
self._type = type
|
||||
self._free = freespace
|
||||
self._mountpoint = mountpoint
|
||||
|
||||
class NoProvider(Event):
|
||||
"""No Provider for an Event"""
|
||||
|
||||
@@ -32,14 +32,7 @@ class TracebackEntry(namedtuple.abc):
|
||||
def _get_frame_args(frame):
|
||||
"""Get the formatted arguments and class (if available) for a frame"""
|
||||
arginfo = inspect.getargvalues(frame)
|
||||
|
||||
try:
|
||||
if not arginfo.args:
|
||||
return '', None
|
||||
# There have been reports from the field of python 2.6 which doesn't
|
||||
# return a namedtuple here but simply a tuple so fallback gracefully if
|
||||
# args isn't present.
|
||||
except AttributeError:
|
||||
if not arginfo.args:
|
||||
return '', None
|
||||
|
||||
firstarg = arginfo.args[0]
|
||||
|
||||
@@ -8,7 +8,6 @@ BitBake build tools.
|
||||
"""
|
||||
|
||||
# Copyright (C) 2003, 2004 Chris Larson
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
@@ -29,13 +28,10 @@ from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
import os, re
|
||||
import logging
|
||||
import urllib
|
||||
import bb.persist_data, bb.utils
|
||||
import bb.checksum
|
||||
from bb import data
|
||||
|
||||
__version__ = "2"
|
||||
_checksum_cache = bb.checksum.FileChecksumCache()
|
||||
|
||||
logger = logging.getLogger("BitBake.Fetcher")
|
||||
|
||||
@@ -67,12 +63,6 @@ class FetchError(BBFetchException):
|
||||
BBFetchException.__init__(self, msg)
|
||||
self.args = (message, url)
|
||||
|
||||
class ChecksumError(FetchError):
|
||||
"""Exception when mismatched checksum encountered"""
|
||||
|
||||
class NoChecksumError(FetchError):
|
||||
"""Exception when no checksum is specified, but BB_STRICT_CHECKSUM is set"""
|
||||
|
||||
class UnpackError(BBFetchException):
|
||||
"""General fetcher exception when something happens incorrectly when unpacking"""
|
||||
def __init__(self, message, url):
|
||||
@@ -109,15 +99,12 @@ class ParameterError(BBFetchException):
|
||||
class NetworkAccess(BBFetchException):
|
||||
"""Exception raised when network access is disabled but it is required."""
|
||||
def __init__(self, url, cmd):
|
||||
msg = "Network access disabled through BB_NO_NETWORK but access requested with command %s (for url %s)" % (cmd, url)
|
||||
msg = "Network access disabled through BB_NO_NETWORK but access rquested with command %s (for url %s)" % (cmd, url)
|
||||
self.url = url
|
||||
self.cmd = cmd
|
||||
BBFetchException.__init__(self, msg)
|
||||
self.args = (url, cmd)
|
||||
|
||||
class NonLocalMethod(Exception):
|
||||
def __init__(self):
|
||||
Exception.__init__(self)
|
||||
|
||||
def decodeurl(url):
|
||||
"""Decodes an URL into the tokens (scheme, network location, path,
|
||||
@@ -157,14 +144,14 @@ def decodeurl(url):
|
||||
s1, s2 = s.split('=')
|
||||
p[s1] = s2
|
||||
|
||||
return type, host, urllib.unquote(path), user, pswd, p
|
||||
return (type, host, path, user, pswd, p)
|
||||
|
||||
def encodeurl(decoded):
|
||||
"""Encodes a URL from tokens (scheme, network location, path,
|
||||
user, password, parameters).
|
||||
"""
|
||||
|
||||
type, host, path, user, pswd, p = decoded
|
||||
(type, host, path, user, pswd, p) = decoded
|
||||
|
||||
if not path:
|
||||
raise MissingParameterError('path', "encoded from the data %s" % str(decoded))
|
||||
@@ -178,14 +165,14 @@ def encodeurl(decoded):
|
||||
url += "@"
|
||||
if host and type != "file":
|
||||
url += "%s" % host
|
||||
url += "%s" % urllib.quote(path)
|
||||
url += "%s" % path
|
||||
if p:
|
||||
for parm in p:
|
||||
url += ";%s=%s" % (parm, p[parm])
|
||||
|
||||
return url
|
||||
|
||||
def uri_replace(ud, uri_find, uri_replace, replacements, d):
|
||||
def uri_replace(ud, uri_find, uri_replace, d):
|
||||
if not ud.url or not uri_find or not uri_replace:
|
||||
logger.error("uri_replace: passed an undefined value, not replacing")
|
||||
return None
|
||||
@@ -194,45 +181,27 @@ def uri_replace(ud, uri_find, uri_replace, replacements, d):
|
||||
uri_replace_decoded = list(decodeurl(uri_replace))
|
||||
logger.debug(2, "For url %s comparing %s to %s" % (uri_decoded, uri_find_decoded, uri_replace_decoded))
|
||||
result_decoded = ['', '', '', '', '', {}]
|
||||
for loc, i in enumerate(uri_find_decoded):
|
||||
for i in uri_find_decoded:
|
||||
loc = uri_find_decoded.index(i)
|
||||
result_decoded[loc] = uri_decoded[loc]
|
||||
regexp = i
|
||||
if loc == 0 and regexp and not regexp.endswith("$"):
|
||||
# Leaving the type unanchored can mean "https" matching "file" can become "files"
|
||||
# which is clearly undesirable.
|
||||
regexp += "$"
|
||||
if loc == 5:
|
||||
# Handle URL parameters
|
||||
if i:
|
||||
# Any specified URL parameters must match
|
||||
for k in uri_replace_decoded[loc]:
|
||||
if uri_decoded[loc][k] != uri_replace_decoded[loc][k]:
|
||||
return None
|
||||
# Overwrite any specified replacement parameters
|
||||
for k in uri_replace_decoded[loc]:
|
||||
result_decoded[loc][k] = uri_replace_decoded[loc][k]
|
||||
elif (re.match(regexp, uri_decoded[loc])):
|
||||
if not uri_replace_decoded[loc]:
|
||||
result_decoded[loc] = ""
|
||||
if isinstance(i, basestring):
|
||||
if (re.match(i, uri_decoded[loc])):
|
||||
if not uri_replace_decoded[loc]:
|
||||
result_decoded[loc] = ""
|
||||
else:
|
||||
result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
|
||||
if uri_find_decoded.index(i) == 2:
|
||||
basename = None
|
||||
if ud.mirrortarball:
|
||||
basename = os.path.basename(ud.mirrortarball)
|
||||
elif ud.localpath:
|
||||
basename = os.path.basename(ud.localpath)
|
||||
if basename and result_decoded[loc].endswith("/"):
|
||||
result_decoded[loc] = os.path.dirname(result_decoded[loc])
|
||||
if basename and not result_decoded[loc].endswith(basename):
|
||||
result_decoded[loc] = os.path.join(result_decoded[loc], basename)
|
||||
else:
|
||||
for k in replacements:
|
||||
uri_replace_decoded[loc] = uri_replace_decoded[loc].replace(k, replacements[k])
|
||||
#bb.note("%s %s %s" % (regexp, uri_replace_decoded[loc], uri_decoded[loc]))
|
||||
result_decoded[loc] = re.sub(regexp, uri_replace_decoded[loc], uri_decoded[loc])
|
||||
if loc == 2:
|
||||
# Handle path manipulations
|
||||
basename = None
|
||||
if uri_decoded[0] != uri_replace_decoded[0] and ud.mirrortarball:
|
||||
# If the source and destination url types differ, must be a mirrortarball mapping
|
||||
basename = os.path.basename(ud.mirrortarball)
|
||||
# Kill parameters, they make no sense for mirror tarballs
|
||||
uri_decoded[5] = {}
|
||||
elif ud.localpath and ud.method.supports_checksum(ud):
|
||||
basename = os.path.basename(ud.localpath)
|
||||
if basename and not result_decoded[loc].endswith(basename):
|
||||
result_decoded[loc] = os.path.join(result_decoded[loc], basename)
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
result = encodeurl(result_decoded)
|
||||
if result == ud.url:
|
||||
return None
|
||||
@@ -263,18 +232,10 @@ def fetcher_init(d):
|
||||
else:
|
||||
raise FetchError("Invalid SRCREV cache policy of: %s" % srcrev_policy)
|
||||
|
||||
_checksum_cache.init_cache(d)
|
||||
|
||||
for m in methods:
|
||||
if hasattr(m, "init"):
|
||||
m.init(d)
|
||||
|
||||
def fetcher_parse_save(d):
|
||||
_checksum_cache.save_extras(d)
|
||||
|
||||
def fetcher_parse_done(d):
|
||||
_checksum_cache.save_merge(d)
|
||||
|
||||
def fetcher_compare_revisions(d):
|
||||
"""
|
||||
Compare the revisions in the persistant cache with current values and
|
||||
@@ -301,37 +262,39 @@ def verify_checksum(u, ud, d):
|
||||
"""
|
||||
verify the MD5 and SHA256 checksum for downloaded src
|
||||
|
||||
Raises a FetchError if one or both of the SRC_URI checksums do not match
|
||||
the downloaded file, or if BB_STRICT_CHECKSUM is set and there are no
|
||||
checksums specified.
|
||||
return value:
|
||||
- True: a checksum matched
|
||||
- False: neither checksum matched
|
||||
|
||||
if checksum is missing in recipes file, "BB_STRICT_CHECKSUM" decide the return value.
|
||||
if BB_STRICT_CHECKSUM = "1" then return false as unmatched, otherwise return true as
|
||||
matched
|
||||
"""
|
||||
|
||||
if not ud.method.supports_checksum(ud):
|
||||
if not ud.type in ["http", "https", "ftp", "ftps"]:
|
||||
return
|
||||
|
||||
md5data = bb.utils.md5_file(ud.localpath)
|
||||
sha256data = bb.utils.sha256_file(ud.localpath)
|
||||
|
||||
if ud.method.recommends_checksum(ud):
|
||||
# If strict checking enabled and neither sum defined, raise error
|
||||
strict = d.getVar("BB_STRICT_CHECKSUM", True) or None
|
||||
if (strict and ud.md5_expected == None and ud.sha256_expected == None):
|
||||
raise NoChecksumError('No checksum specified for %s, please add at least one to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
|
||||
(ud.localpath, ud.md5_name, md5data,
|
||||
ud.sha256_name, sha256data), u)
|
||||
# If strict checking enabled and neither sum defined, raise error
|
||||
strict = d.getVar("BB_STRICT_CHECKSUM", True) or None
|
||||
if (strict and ud.md5_expected == None and ud.sha256_expected == None):
|
||||
raise FetchError('No checksum specified for %s, please add at least one to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
|
||||
(ud.localpath, ud.md5_name, md5data,
|
||||
ud.sha256_name, sha256data), u)
|
||||
|
||||
# Log missing sums so user can more easily add them
|
||||
if ud.md5_expected == None:
|
||||
logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"',
|
||||
ud.localpath, ud.md5_name, md5data)
|
||||
# Log missing sums so user can more easily add them
|
||||
if ud.md5_expected == None:
|
||||
logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"',
|
||||
ud.localpath, ud.md5_name, md5data)
|
||||
|
||||
if ud.sha256_expected == None:
|
||||
logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"',
|
||||
ud.localpath, ud.sha256_name, sha256data)
|
||||
if ud.sha256_expected == None:
|
||||
logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
|
||||
'SRC_URI[%s] = "%s"',
|
||||
ud.localpath, ud.sha256_name, sha256data)
|
||||
|
||||
md5mismatch = False
|
||||
sha256mismatch = False
|
||||
@@ -345,20 +308,14 @@ def verify_checksum(u, ud, d):
|
||||
# We want to alert the user if a checksum is defined in the recipe but
|
||||
# it does not match.
|
||||
msg = ""
|
||||
mismatch = False
|
||||
if md5mismatch and ud.md5_expected:
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'md5', md5data, ud.md5_expected)
|
||||
mismatch = True;
|
||||
|
||||
if sha256mismatch and ud.sha256_expected:
|
||||
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected)
|
||||
mismatch = True;
|
||||
|
||||
if mismatch:
|
||||
msg = msg + '\nYour checksums:\nSRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' % (ud.md5_name, md5data, ud.sha256_name, sha256data)
|
||||
|
||||
if len(msg):
|
||||
raise ChecksumError('Checksum mismatch!%s' % msg, u)
|
||||
raise FetchError('Checksum mismatch!%s' % msg, u)
|
||||
|
||||
|
||||
def update_stamp(u, ud, d):
|
||||
@@ -467,10 +424,11 @@ def runfetchcmd(cmd, d, quiet = False, cleanup = []):
|
||||
success = True
|
||||
except bb.process.NotFoundError as e:
|
||||
error_message = "Fetch command %s" % (e.command)
|
||||
except bb.process.ExecutionError as e:
|
||||
error_message = "Fetch command %s failed with exit code %s, output:\nSTDOUT: %s\nSTDERR: %s" % (e.command, e.exitcode, e.stdout, e.stderr)
|
||||
except bb.process.CmdError as e:
|
||||
error_message = "Fetch command %s could not be run:\n%s" % (e.command, e.msg)
|
||||
except bb.process.ExecutionError as e:
|
||||
error_message = "Fetch command %s failed with exit code %s, output:\n%s" % (e.command, e.exitcode, e.stderr)
|
||||
|
||||
if not success:
|
||||
for f in cleanup:
|
||||
try:
|
||||
@@ -495,20 +453,13 @@ def build_mirroruris(origud, mirrors, ld):
|
||||
uris = []
|
||||
uds = []
|
||||
|
||||
replacements = {}
|
||||
replacements["TYPE"] = origud.type
|
||||
replacements["HOST"] = origud.host
|
||||
replacements["PATH"] = origud.path
|
||||
replacements["BASENAME"] = origud.path.split("/")[-1]
|
||||
replacements["MIRRORNAME"] = origud.host.replace(':','.') + origud.path.replace('/', '.').replace('*', '.')
|
||||
|
||||
def adduri(uri, ud, uris, uds):
|
||||
for line in mirrors:
|
||||
try:
|
||||
(find, replace) = line
|
||||
except ValueError:
|
||||
continue
|
||||
newuri = uri_replace(ud, find, replace, replacements, ld)
|
||||
newuri = uri_replace(ud, find, replace, ld)
|
||||
if not newuri or newuri in uris or newuri == origud.url:
|
||||
continue
|
||||
try:
|
||||
@@ -566,11 +517,7 @@ def try_mirror_url(newuri, origud, ud, ld, check = False):
|
||||
return None
|
||||
# Otherwise the result is a local file:// and we symlink to it
|
||||
if not os.path.exists(origud.localpath):
|
||||
if os.path.islink(origud.localpath):
|
||||
# Broken symbolic link
|
||||
os.unlink(origud.localpath)
|
||||
|
||||
os.symlink(ud.localpath, origud.localpath)
|
||||
os.symlink(ud.localpath, origud.localpath)
|
||||
update_stamp(newuri, origud, ld)
|
||||
return ud.localpath
|
||||
|
||||
@@ -578,14 +525,8 @@ def try_mirror_url(newuri, origud, ud, ld, check = False):
|
||||
raise
|
||||
|
||||
except bb.fetch2.BBFetchException as e:
|
||||
if isinstance(e, ChecksumError):
|
||||
logger.warn("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (newuri, origud.url))
|
||||
logger.warn(str(e))
|
||||
elif isinstance(e, NoChecksumError):
|
||||
raise
|
||||
else:
|
||||
logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
|
||||
logger.debug(1, str(e))
|
||||
logger.debug(1, "Mirror fetch failure for url %s (original url: %s)" % (newuri, origud.url))
|
||||
logger.debug(1, str(e))
|
||||
try:
|
||||
ud.method.clean(ud, ld)
|
||||
except UnboundLocalError:
|
||||
@@ -642,85 +583,11 @@ def srcrev_internal_helper(ud, d, name):
|
||||
|
||||
return rev
|
||||
|
||||
|
||||
def get_checksum_file_list(d):
|
||||
""" Get a list of files checksum in SRC_URI
|
||||
|
||||
Returns the resolved local paths of all local file entries in
|
||||
SRC_URI as a space-separated string
|
||||
"""
|
||||
fetch = Fetch([], d, cache = False, localonly = True)
|
||||
|
||||
dl_dir = d.getVar('DL_DIR', True)
|
||||
filelist = []
|
||||
for u in fetch.urls:
|
||||
ud = fetch.ud[u]
|
||||
|
||||
if ud and isinstance(ud.method, local.Local):
|
||||
ud.setup_localpath(d)
|
||||
f = ud.localpath
|
||||
if f.startswith(dl_dir):
|
||||
# The local fetcher's behaviour is to return a path under DL_DIR if it couldn't find the file anywhere else
|
||||
if os.path.exists(f):
|
||||
bb.warn("Getting checksum for %s SRC_URI entry %s: file not found except in DL_DIR" % (d.getVar('PN', True), os.path.basename(f)))
|
||||
else:
|
||||
bb.warn("Unable to get checksum for %s SRC_URI entry %s: file could not be found" % (d.getVar('PN', True), os.path.basename(f)))
|
||||
continue
|
||||
filelist.append(f)
|
||||
|
||||
return " ".join(filelist)
|
||||
|
||||
|
||||
def get_file_checksums(filelist, pn):
|
||||
"""Get a list of the checksums for a list of local files
|
||||
|
||||
Returns the checksums for a list of local files, caching the results as
|
||||
it proceeds
|
||||
|
||||
"""
|
||||
|
||||
def checksum_file(f):
|
||||
try:
|
||||
checksum = _checksum_cache.get_checksum(f)
|
||||
except OSError as e:
|
||||
import traceback
|
||||
bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
|
||||
return None
|
||||
return checksum
|
||||
|
||||
checksums = []
|
||||
for pth in filelist.split():
|
||||
checksum = None
|
||||
if '*' in pth:
|
||||
# Handle globs
|
||||
import glob
|
||||
for f in glob.glob(pth):
|
||||
checksum = checksum_file(f)
|
||||
if checksum:
|
||||
checksums.append((f, checksum))
|
||||
elif os.path.isdir(pth):
|
||||
# Handle directories
|
||||
for root, dirs, files in os.walk(pth):
|
||||
for name in files:
|
||||
fullpth = os.path.join(root, name)
|
||||
checksum = checksum_file(fullpth)
|
||||
if checksum:
|
||||
checksums.append((fullpth, checksum))
|
||||
else:
|
||||
checksum = checksum_file(pth)
|
||||
|
||||
if checksum:
|
||||
checksums.append((pth, checksum))
|
||||
|
||||
checksums.sort()
|
||||
return checksums
|
||||
|
||||
|
||||
class FetchData(object):
|
||||
"""
|
||||
A class which represents the fetcher state for a given URI.
|
||||
"""
|
||||
def __init__(self, url, d, localonly = False):
|
||||
def __init__(self, url, d):
|
||||
# localpath is the location of a downloaded result. If not set, the file is local.
|
||||
self.donestamp = None
|
||||
self.localfile = ""
|
||||
@@ -745,14 +612,10 @@ class FetchData(object):
|
||||
self.sha256_name = "sha256sum"
|
||||
if self.md5_name in self.parm:
|
||||
self.md5_expected = self.parm[self.md5_name]
|
||||
elif self.type not in ["http", "https", "ftp", "ftps"]:
|
||||
self.md5_expected = None
|
||||
else:
|
||||
self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name)
|
||||
if self.sha256_name in self.parm:
|
||||
self.sha256_expected = self.parm[self.sha256_name]
|
||||
elif self.type not in ["http", "https", "ftp", "ftps"]:
|
||||
self.sha256_expected = None
|
||||
else:
|
||||
self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name)
|
||||
|
||||
@@ -767,13 +630,6 @@ class FetchData(object):
|
||||
if not self.method:
|
||||
raise NoMethodError(url)
|
||||
|
||||
if localonly and not isinstance(self.method, local.Local):
|
||||
raise NonLocalMethod()
|
||||
|
||||
if self.parm.get("proto", None) and "protocol" not in self.parm:
|
||||
logger.warn('Consider updating %s recipe to use "protocol" not "proto" in SRC_URI.', d.getVar('PN', True))
|
||||
self.parm["protocol"] = self.parm.get("proto", None)
|
||||
|
||||
if hasattr(self.method, "urldata_init"):
|
||||
self.method.urldata_init(self, d)
|
||||
|
||||
@@ -838,26 +694,6 @@ class FetchMethod(object):
|
||||
"""
|
||||
return os.path.join(data.getVar("DL_DIR", d, True), urldata.localfile)
|
||||
|
||||
def supports_checksum(self, urldata):
|
||||
"""
|
||||
Is localpath something that can be represented by a checksum?
|
||||
"""
|
||||
|
||||
# We cannot compute checksums for directories
|
||||
if os.path.isdir(urldata.localpath) == True:
|
||||
return False
|
||||
if urldata.localpath.find("*") != -1:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def recommends_checksum(self, urldata):
|
||||
"""
|
||||
Is the backend on where checksumming is recommended (should warnings
|
||||
by displayed if there is no checksum)?
|
||||
"""
|
||||
return False
|
||||
|
||||
def _strip_leading_slashes(self, relpath):
|
||||
"""
|
||||
Remove leading slash as os.path.join can't cope
|
||||
@@ -908,7 +744,7 @@ class FetchMethod(object):
|
||||
|
||||
dots = file.split(".")
|
||||
if dots[-1] in ['gz', 'bz2', 'Z']:
|
||||
efile = os.path.join(rootdir, os.path.basename('.'.join(dots[0:-1])))
|
||||
efile = os.path.join(data.getVar('WORKDIR', True),os.path.basename('.'.join(dots[0:-1])))
|
||||
else:
|
||||
efile = file
|
||||
cmd = None
|
||||
@@ -984,9 +820,7 @@ class FetchMethod(object):
|
||||
bb.utils.mkdirhier(newdir)
|
||||
os.chdir(newdir)
|
||||
|
||||
path = data.getVar('PATH', True)
|
||||
if path:
|
||||
cmd = "PATH=\"%s\" %s" % (path, cmd)
|
||||
cmd = "PATH=\"%s\" %s" % (data.getVar('PATH', True), cmd)
|
||||
bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
|
||||
ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True)
|
||||
|
||||
@@ -1097,10 +931,7 @@ class FetchMethod(object):
|
||||
return "%s-%s" % (key, d.getVar("PN", True) or "")
|
||||
|
||||
class Fetch(object):
|
||||
def __init__(self, urls, d, cache = True, localonly = False):
|
||||
if localonly and cache:
|
||||
raise Exception("bb.fetch2.Fetch.__init__: cannot set cache and localonly at same time")
|
||||
|
||||
def __init__(self, urls, d, cache = True):
|
||||
if len(urls) == 0:
|
||||
urls = d.getVar("SRC_URI", True).split()
|
||||
self.urls = urls
|
||||
@@ -1113,12 +944,7 @@ class Fetch(object):
|
||||
|
||||
for url in urls:
|
||||
if url not in self.ud:
|
||||
try:
|
||||
self.ud[url] = FetchData(url, d, localonly)
|
||||
except NonLocalMethod:
|
||||
if localonly:
|
||||
self.ud[url] = None
|
||||
pass
|
||||
self.ud[url] = FetchData(url, d)
|
||||
|
||||
if fn and cache:
|
||||
urldata_cache[fn] = self.ud
|
||||
@@ -1192,16 +1018,12 @@ class Fetch(object):
|
||||
raise
|
||||
|
||||
except BBFetchException as e:
|
||||
if isinstance(e, ChecksumError):
|
||||
logger.warn("Checksum error encountered with download (will attempt other sources): %s" % str(e))
|
||||
if isinstance(e, NoChecksumError):
|
||||
raise
|
||||
else:
|
||||
logger.warn('Failed to fetch URL %s, attempting MIRRORS if available' % u)
|
||||
logger.debug(1, str(e))
|
||||
logger.warn('Failed to fetch URL %s' % u)
|
||||
logger.debug(1, str(e))
|
||||
firsterr = e
|
||||
# Remove any incomplete fetch
|
||||
m.clean(ud, self.d)
|
||||
if os.path.isfile(ud.localpath):
|
||||
bb.utils.remove(ud.localpath)
|
||||
logger.debug(1, "Trying MIRRORS")
|
||||
mirrors = mirror_from_string(self.d.getVar('MIRRORS', True))
|
||||
localpath = try_mirrors (self.d, ud, mirrors)
|
||||
@@ -1213,11 +1035,6 @@ class Fetch(object):
|
||||
|
||||
update_stamp(u, ud, self.d)
|
||||
|
||||
except BBFetchException as e:
|
||||
if isinstance(e, NoChecksumError):
|
||||
logger.error("%s" % str(e))
|
||||
raise
|
||||
|
||||
finally:
|
||||
bb.utils.unlockfile(lf)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class Bzr(FetchMethod):
|
||||
|
||||
basecmd = data.expand('${FETCHCMD_bzr}', d)
|
||||
|
||||
proto = ud.parm.get('protocol', 'http')
|
||||
proto = ud.parm.get('proto', 'http')
|
||||
|
||||
bzrroot = ud.host + ud.path
|
||||
|
||||
@@ -73,7 +73,7 @@ class Bzr(FetchMethod):
|
||||
options.append("-r %s" % ud.revision)
|
||||
|
||||
if command == "fetch":
|
||||
bzrcmd = "%s branch %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
|
||||
bzrcmd = "%s co %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
|
||||
elif command == "update":
|
||||
bzrcmd = "%s pull %s --overwrite" % (basecmd, " ".join(options))
|
||||
else:
|
||||
|
||||
@@ -111,9 +111,15 @@ class Cvs(FetchMethod):
|
||||
if ud.tag:
|
||||
options.append("-r %s" % ud.tag)
|
||||
|
||||
cvsbasecmd = d.getVar("FETCHCMD_cvs", True)
|
||||
cvscmd = cvsbasecmd + "'-d" + cvsroot + "' co " + " ".join(options) + " " + ud.module
|
||||
cvsupdatecmd = cvsbasecmd + "'-d" + cvsroot + "' update -d -P " + " ".join(options)
|
||||
localdata = data.createCopy(d)
|
||||
data.setVar('OVERRIDES', "cvs:%s" % data.getVar('OVERRIDES', localdata), localdata)
|
||||
data.update_data(localdata)
|
||||
|
||||
data.setVar('CVSROOT', cvsroot, localdata)
|
||||
data.setVar('CVSCOOPTS', " ".join(options), localdata)
|
||||
data.setVar('CVSMODULE', ud.module, localdata)
|
||||
cvscmd = data.getVar('FETCHCOMMAND', localdata, True)
|
||||
cvsupdatecmd = data.getVar('UPDATECOMMAND', localdata, True)
|
||||
|
||||
if cvs_rsh:
|
||||
cvscmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvscmd)
|
||||
|
||||
@@ -82,9 +82,6 @@ class Git(FetchMethod):
|
||||
"""
|
||||
return ud.type in ['git']
|
||||
|
||||
def supports_checksum(self, urldata):
|
||||
return False
|
||||
|
||||
def urldata_init(self, ud, d):
|
||||
"""
|
||||
init git specific variable within url data
|
||||
@@ -126,11 +123,10 @@ class Git(FetchMethod):
|
||||
for name in ud.names:
|
||||
# Ensure anything that doesn't look like a sha256 checksum/revision is translated into one
|
||||
if not ud.revisions[name] or len(ud.revisions[name]) != 40 or (False in [c in "abcdef0123456789" for c in ud.revisions[name]]):
|
||||
if ud.revisions[name]:
|
||||
ud.branches[name] = ud.revisions[name]
|
||||
ud.branches[name] = ud.revisions[name]
|
||||
ud.revisions[name] = self.latest_revision(ud.url, ud, d, name)
|
||||
|
||||
gitsrcname = '%s%s' % (ud.host.replace(':','.'), ud.path.replace('/', '.').replace('*', '.'))
|
||||
gitsrcname = '%s%s' % (ud.host.replace(':','.'), ud.path.replace('/', '.'))
|
||||
# for rebaseable git repo, it is necessary to keep mirror tar ball
|
||||
# per revision, so that even the revision disappears from the
|
||||
# upstream repo in the future, the mirror will remain intact and still
|
||||
@@ -139,9 +135,8 @@ class Git(FetchMethod):
|
||||
for name in ud.names:
|
||||
gitsrcname = gitsrcname + '_' + ud.revisions[name]
|
||||
ud.mirrortarball = 'git2_%s.tar.gz' % (gitsrcname)
|
||||
ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
|
||||
gitdir = d.getVar("GITDIR", True) or (d.getVar("DL_DIR", True) + "/git2/")
|
||||
ud.clonedir = os.path.join(gitdir, gitsrcname)
|
||||
ud.fullmirror = os.path.join(data.getVar("DL_DIR", d, True), ud.mirrortarball)
|
||||
ud.clonedir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
|
||||
|
||||
ud.localfile = ud.clonedir
|
||||
|
||||
@@ -188,12 +183,8 @@ class Git(FetchMethod):
|
||||
|
||||
# If the repo still doesn't exist, fallback to cloning it
|
||||
if not os.path.exists(ud.clonedir):
|
||||
# We do this since git will use a "-l" option automatically for local urls where possible
|
||||
if repourl.startswith("file://"):
|
||||
repourl = repourl[7:]
|
||||
clone_cmd = "%s clone --bare --mirror %s %s" % (ud.basecmd, repourl, ud.clonedir)
|
||||
if ud.proto.lower() != 'file':
|
||||
bb.fetch2.check_network_access(d, clone_cmd)
|
||||
bb.fetch2.check_network_access(d, clone_cmd)
|
||||
runfetchcmd(clone_cmd, d)
|
||||
|
||||
os.chdir(ud.clonedir)
|
||||
@@ -204,14 +195,14 @@ class Git(FetchMethod):
|
||||
needupdate = True
|
||||
if needupdate:
|
||||
try:
|
||||
runfetchcmd("%s remote prune origin" % ud.basecmd, d)
|
||||
runfetchcmd("%s remote rm origin" % ud.basecmd, d)
|
||||
except bb.fetch2.FetchError:
|
||||
logger.debug(1, "No Origin")
|
||||
|
||||
runfetchcmd("%s remote add --mirror=fetch origin %s" % (ud.basecmd, repourl), d)
|
||||
fetch_cmd = "%s fetch -f --prune %s refs/*:refs/*" % (ud.basecmd, repourl)
|
||||
if ud.proto.lower() != 'file':
|
||||
bb.fetch2.check_network_access(d, fetch_cmd, ud.url)
|
||||
bb.fetch2.check_network_access(d, fetch_cmd, ud.url)
|
||||
runfetchcmd(fetch_cmd, d)
|
||||
runfetchcmd("%s prune-packed" % ud.basecmd, d)
|
||||
runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d)
|
||||
@@ -290,8 +281,7 @@ class Git(FetchMethod):
|
||||
basecmd = data.getVar("FETCHCMD_git", d, True) or "git"
|
||||
cmd = "%s ls-remote %s://%s%s%s %s" % \
|
||||
(basecmd, ud.proto, username, ud.host, ud.path, ud.branches[name])
|
||||
if ud.proto.lower() != 'file':
|
||||
bb.fetch2.check_network_access(d, cmd)
|
||||
bb.fetch2.check_network_access(d, cmd)
|
||||
output = runfetchcmd(cmd, d, True)
|
||||
if not output:
|
||||
raise bb.fetch2.FetchError("The command %s gave empty output unexpectedly" % cmd, url)
|
||||
|
||||
@@ -82,7 +82,7 @@ class Hg(FetchMethod):
|
||||
|
||||
basecmd = data.expand('${FETCHCMD_hg}', d)
|
||||
|
||||
proto = ud.parm.get('protocol', 'http')
|
||||
proto = ud.parm.get('proto', 'http')
|
||||
|
||||
host = ud.host
|
||||
if proto == "file":
|
||||
|
||||
@@ -26,12 +26,10 @@ BitBake build tools.
|
||||
# Based on functions from the base bb module, Copyright 2003 Holger Schurig
|
||||
|
||||
import os
|
||||
import urllib
|
||||
import bb
|
||||
import bb.utils
|
||||
from bb import data
|
||||
from bb.fetch2 import FetchMethod, FetchError
|
||||
from bb.fetch2 import logger
|
||||
from bb.fetch2 import FetchMethod
|
||||
|
||||
class Local(FetchMethod):
|
||||
def supports(self, url, urldata, d):
|
||||
@@ -42,31 +40,27 @@ class Local(FetchMethod):
|
||||
|
||||
def urldata_init(self, ud, d):
|
||||
# We don't set localfile as for this fetcher the file is already local!
|
||||
ud.decodedurl = urllib.unquote(ud.url.split("://")[1].split(";")[0])
|
||||
ud.basename = os.path.basename(ud.decodedurl)
|
||||
ud.basename = os.path.basename(ud.url.split("://")[1].split(";")[0])
|
||||
return
|
||||
|
||||
def localpath(self, url, urldata, d):
|
||||
"""
|
||||
Return the local filename of a given url assuming a successful fetch.
|
||||
"""
|
||||
path = urldata.decodedurl
|
||||
path = url.split("://")[1]
|
||||
path = path.split(";")[0]
|
||||
newpath = path
|
||||
if path[0] != "/":
|
||||
filespath = data.getVar('FILESPATH', d, True)
|
||||
if filespath:
|
||||
logger.debug(2, "Searching for %s in paths: \n%s" % (path, "\n ".join(filespath.split(":"))))
|
||||
newpath = bb.utils.which(filespath, path)
|
||||
if not newpath:
|
||||
filesdir = data.getVar('FILESDIR', d, True)
|
||||
if filesdir:
|
||||
logger.debug(2, "Searching for %s in path: %s" % (path, filesdir))
|
||||
newpath = os.path.join(filesdir, path)
|
||||
if not os.path.exists(newpath) and path.find("*") == -1:
|
||||
dldirfile = os.path.join(d.getVar("DL_DIR", True), path)
|
||||
logger.debug(2, "Defaulting to %s for %s" % (dldirfile, path))
|
||||
bb.utils.mkdirhier(os.path.dirname(dldirfile))
|
||||
return dldirfile
|
||||
if not os.path.exists(newpath) and path.find("*") == -1:
|
||||
dldirfile = os.path.join(data.getVar("DL_DIR", d, True), os.path.basename(path))
|
||||
return dldirfile
|
||||
return newpath
|
||||
|
||||
def need_update(self, url, ud, d):
|
||||
@@ -79,20 +73,7 @@ class Local(FetchMethod):
|
||||
def download(self, url, urldata, d):
|
||||
"""Fetch urls (no-op for Local method)"""
|
||||
# no need to fetch local files, we'll deal with them in place.
|
||||
if self.supports_checksum(urldata) and not os.path.exists(urldata.localpath):
|
||||
locations = []
|
||||
filespath = data.getVar('FILESPATH', d, True)
|
||||
if filespath:
|
||||
locations = filespath.split(":")
|
||||
filesdir = data.getVar('FILESDIR', d, True)
|
||||
if filesdir:
|
||||
locations.append(filesdir)
|
||||
locations.append(d.getVar("DL_DIR", True))
|
||||
|
||||
msg = "Unable to find file " + url + " anywhere. The paths that were searched were:\n " + "\n ".join(locations)
|
||||
raise FetchError(msg)
|
||||
|
||||
return True
|
||||
return 1
|
||||
|
||||
def checkstatus(self, url, urldata, d):
|
||||
"""
|
||||
|
||||
@@ -57,7 +57,7 @@ class Osc(FetchMethod):
|
||||
|
||||
basecmd = data.expand('${FETCHCMD_osc}', d)
|
||||
|
||||
proto = ud.parm.get('protocol', 'ocs')
|
||||
proto = ud.parm.get('proto', 'ocs')
|
||||
|
||||
options = []
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ BitBake build tools.
|
||||
|
||||
from future_builtins import zip
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
import bb
|
||||
from bb import data
|
||||
@@ -91,8 +90,8 @@ class Perforce(FetchMethod):
|
||||
|
||||
p4cmd = data.getVar('FETCHCOMMAND_p4', d, True)
|
||||
logger.debug(1, "Running %s%s changes -m 1 %s", p4cmd, p4opt, depot)
|
||||
p4file, errors = bb.process.run("%s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
|
||||
cset = p4file.strip()
|
||||
p4file = os.popen("%s%s changes -m 1 %s" % (p4cmd, p4opt, depot))
|
||||
cset = p4file.readline().strip()
|
||||
logger.debug(1, "READ %s", cset)
|
||||
if not cset:
|
||||
return -1
|
||||
@@ -155,8 +154,8 @@ class Perforce(FetchMethod):
|
||||
logger.debug(2, "Fetch: creating temporary directory")
|
||||
bb.utils.mkdirhier(data.expand('${WORKDIR}', localdata))
|
||||
data.setVar('TMPBASE', data.expand('${WORKDIR}/oep4.XXXXXX', localdata), localdata)
|
||||
tmpfile, errors = bb.process.run(data.getVar('MKTEMPDIRCMD', localdata, True) or "false")
|
||||
tmpfile = tmpfile.strip()
|
||||
tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, True) or "false")
|
||||
tmpfile = tmppipe.readline().strip()
|
||||
if not tmpfile:
|
||||
raise FetchError("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.", loc)
|
||||
|
||||
@@ -169,8 +168,7 @@ class Perforce(FetchMethod):
|
||||
os.chdir(tmpfile)
|
||||
logger.info("Fetch " + loc)
|
||||
logger.info("%s%s files %s", p4cmd, p4opt, depot)
|
||||
p4file, errors = bb.process.run("%s%s files %s" % (p4cmd, p4opt, depot))
|
||||
p4file = p4file.strip()
|
||||
p4file = os.popen("%s%s files %s" % (p4cmd, p4opt, depot))
|
||||
|
||||
if not p4file:
|
||||
raise FetchError("Fetch: unable to get the P4 files from %s" % depot, loc)
|
||||
@@ -186,7 +184,7 @@ class Perforce(FetchMethod):
|
||||
dest = list[0][len(path)+1:]
|
||||
where = dest.find("#")
|
||||
|
||||
subprocess.call("%s%s print -o %s/%s %s" % (p4cmd, p4opt, module, dest[:where], list[0]), shell=True)
|
||||
os.system("%s%s print -o %s/%s %s" % (p4cmd, p4opt, module, dest[:where], list[0]))
|
||||
count = count + 1
|
||||
|
||||
if count == 0:
|
||||
|
||||
@@ -69,9 +69,6 @@ class SSH(FetchMethod):
|
||||
def supports(self, url, urldata, d):
|
||||
return __pattern__.match(url) != None
|
||||
|
||||
def supports_checksum(self, urldata):
|
||||
return False
|
||||
|
||||
def localpath(self, url, urldata, d):
|
||||
m = __pattern__.match(urldata.url)
|
||||
path = m.group('path')
|
||||
|
||||
@@ -77,8 +77,8 @@ class Svk(FetchMethod):
|
||||
logger.debug(2, "Fetch: creating temporary directory")
|
||||
bb.utils.mkdirhier(data.expand('${WORKDIR}', localdata))
|
||||
data.setVar('TMPBASE', data.expand('${WORKDIR}/oesvk.XXXXXX', localdata), localdata)
|
||||
tmpfile, errors = bb.process.run(data.getVar('MKTEMPDIRCMD', localdata, True) or "false")
|
||||
tmpfile = tmpfile.strip()
|
||||
tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, True) or "false")
|
||||
tmpfile = tmppipe.readline().strip()
|
||||
if not tmpfile:
|
||||
logger.error()
|
||||
raise FetchError("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.", loc)
|
||||
|
||||
@@ -49,8 +49,6 @@ class Svn(FetchMethod):
|
||||
if not "module" in ud.parm:
|
||||
raise MissingParameterError('module', ud.url)
|
||||
|
||||
ud.basecmd = d.getVar('FETCHCMD_svn', True)
|
||||
|
||||
ud.module = ud.parm["module"]
|
||||
|
||||
# Create paths to svn checkouts
|
||||
@@ -71,7 +69,9 @@ class Svn(FetchMethod):
|
||||
command is "fetch", "update", "info"
|
||||
"""
|
||||
|
||||
proto = ud.parm.get('protocol', 'svn')
|
||||
basecmd = data.expand('${FETCHCMD_svn}', d)
|
||||
|
||||
proto = ud.parm.get('proto', 'svn')
|
||||
|
||||
svn_rsh = None
|
||||
if proto == "svn+ssh" and "rsh" in ud.parm:
|
||||
@@ -88,7 +88,7 @@ class Svn(FetchMethod):
|
||||
options.append("--password %s" % ud.pswd)
|
||||
|
||||
if command == "info":
|
||||
svncmd = "%s info %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
|
||||
svncmd = "%s info %s %s://%s/%s/" % (basecmd, " ".join(options), proto, svnroot, ud.module)
|
||||
else:
|
||||
suffix = ""
|
||||
if ud.revision:
|
||||
@@ -96,9 +96,9 @@ class Svn(FetchMethod):
|
||||
suffix = "@%s" % (ud.revision)
|
||||
|
||||
if command == "fetch":
|
||||
svncmd = "%s co %s %s://%s/%s%s %s" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module, suffix, ud.module)
|
||||
svncmd = "%s co %s %s://%s/%s%s %s" % (basecmd, " ".join(options), proto, svnroot, ud.module, suffix, ud.module)
|
||||
elif command == "update":
|
||||
svncmd = "%s update %s" % (ud.basecmd, " ".join(options))
|
||||
svncmd = "%s update %s" % (basecmd, " ".join(options))
|
||||
else:
|
||||
raise FetchError("Invalid svn command %s" % command, ud.url)
|
||||
|
||||
@@ -117,11 +117,6 @@ class Svn(FetchMethod):
|
||||
logger.info("Update " + loc)
|
||||
# update sources there
|
||||
os.chdir(ud.moddir)
|
||||
# We need to attempt to run svn upgrade first in case its an older working format
|
||||
try:
|
||||
runfetchcmd(ud.basecmd + " upgrade", d)
|
||||
except FetchError:
|
||||
pass
|
||||
logger.debug(1, "Running %s", svnupdatecmd)
|
||||
bb.fetch2.check_network_access(d, svnupdatecmd, ud.url)
|
||||
runfetchcmd(svnupdatecmd, d)
|
||||
|
||||
@@ -45,52 +45,47 @@ class Wget(FetchMethod):
|
||||
"""
|
||||
return ud.type in ['http', 'https', 'ftp']
|
||||
|
||||
def recommends_checksum(self, urldata):
|
||||
return True
|
||||
|
||||
def urldata_init(self, ud, d):
|
||||
|
||||
if 'downloadfilename' in ud.parm:
|
||||
ud.basename = ud.parm['downloadfilename']
|
||||
else:
|
||||
ud.basename = os.path.basename(ud.path)
|
||||
|
||||
ud.basename = os.path.basename(ud.path)
|
||||
ud.localfile = data.expand(urllib.unquote(ud.basename), d)
|
||||
|
||||
def download(self, uri, ud, d, checkonly = False):
|
||||
"""Fetch urls"""
|
||||
|
||||
basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -t 2 -T 30 -nv --passive-ftp --no-check-certificate"
|
||||
def fetch_uri(uri, ud, d):
|
||||
if checkonly:
|
||||
fetchcmd = data.getVar("CHECKCOMMAND", d, True)
|
||||
elif os.path.exists(ud.localpath):
|
||||
# file exists, but we didnt complete it.. trying again..
|
||||
fetchcmd = data.getVar("RESUMECOMMAND", d, True)
|
||||
else:
|
||||
fetchcmd = data.getVar("FETCHCOMMAND", d, True)
|
||||
|
||||
if 'downloadfilename' in ud.parm:
|
||||
basecmd += " -O ${DL_DIR}/" + ud.localfile
|
||||
uri = uri.split(";")[0]
|
||||
uri_decoded = list(decodeurl(uri))
|
||||
uri_type = uri_decoded[0]
|
||||
uri_host = uri_decoded[1]
|
||||
|
||||
if checkonly:
|
||||
fetchcmd = d.getVar("CHECKCOMMAND_wget", True) or d.expand(basecmd + " -c -P ${DL_DIR} '${URI}'")
|
||||
elif os.path.exists(ud.localpath):
|
||||
# file exists, but we didnt complete it.. trying again..
|
||||
fetchcmd = d.getVar("RESUMECOMMAND_wget", True) or d.expand(basecmd + " --spider -P ${DL_DIR} '${URI}'")
|
||||
else:
|
||||
fetchcmd = d.getVar("FETCHCOMMAND_wget", True) or d.expand(basecmd + " -P ${DL_DIR} '${URI}'")
|
||||
fetchcmd = fetchcmd.replace("${URI}", uri.split(";")[0])
|
||||
fetchcmd = fetchcmd.replace("${FILE}", ud.basename)
|
||||
if not checkonly:
|
||||
logger.info("fetch " + uri)
|
||||
logger.debug(2, "executing " + fetchcmd)
|
||||
bb.fetch2.check_network_access(d, fetchcmd)
|
||||
runfetchcmd(fetchcmd, d, quiet=checkonly)
|
||||
|
||||
uri = uri.split(";")[0]
|
||||
uri_decoded = list(decodeurl(uri))
|
||||
uri_type = uri_decoded[0]
|
||||
uri_host = uri_decoded[1]
|
||||
# Sanity check since wget can pretend it succeed when it didn't
|
||||
# Also, this used to happen if sourceforge sent us to the mirror page
|
||||
if not os.path.exists(ud.localpath) and not checkonly:
|
||||
raise FetchError("The fetch command returned success for url %s but %s doesn't exist?!" % (uri, ud.localpath), uri)
|
||||
|
||||
fetchcmd = fetchcmd.replace("${URI}", uri.split(";")[0])
|
||||
fetchcmd = fetchcmd.replace("${FILE}", ud.basename)
|
||||
if not checkonly:
|
||||
logger.info("fetch " + uri)
|
||||
logger.debug(2, "executing " + fetchcmd)
|
||||
bb.fetch2.check_network_access(d, fetchcmd)
|
||||
runfetchcmd(fetchcmd, d, quiet=checkonly)
|
||||
|
||||
# Sanity check since wget can pretend it succeed when it didn't
|
||||
# Also, this used to happen if sourceforge sent us to the mirror page
|
||||
if not os.path.exists(ud.localpath) and not checkonly:
|
||||
raise FetchError("The fetch command returned success for url %s but %s doesn't exist?!" % (uri, ud.localpath), uri)
|
||||
localdata = data.createCopy(d)
|
||||
data.setVar('OVERRIDES', "wget:" + data.getVar('OVERRIDES', localdata), localdata)
|
||||
data.update_data(localdata)
|
||||
|
||||
fetch_uri(uri, ud, localdata)
|
||||
|
||||
return True
|
||||
|
||||
def checkstatus(self, uri, ud, d):
|
||||
|
||||
@@ -52,7 +52,7 @@ def insert_method(modulename, code, fn):
|
||||
if name in ['None', 'False']:
|
||||
continue
|
||||
elif name in _parsed_fns and not _parsed_fns[name] == modulename:
|
||||
error("The function %s defined in %s was already declared in %s. BitBake has a global python function namespace so shared functions should be declared in a common include file rather than being duplicated, or if the functions are different, please use different function names." % (name, modulename, _parsed_fns[name]))
|
||||
error( "Error Method already seen: %s in' %s' now in '%s'" % (name, _parsed_fns[name], modulename))
|
||||
else:
|
||||
_parsed_fns[name] = modulename
|
||||
|
||||
|
||||
@@ -176,7 +176,6 @@ class diskMonitor:
|
||||
def __init__(self, configuration):
|
||||
|
||||
self.enableMonitor = False
|
||||
self.configuration = configuration
|
||||
|
||||
BBDirs = configuration.getVar("BB_DISKMON_DIRS", True) or None
|
||||
if BBDirs:
|
||||
@@ -220,12 +219,10 @@ class diskMonitor:
|
||||
logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(False)
|
||||
bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, self.devDict[dev][1]), self.configuration)
|
||||
elif self.devDict[dev][0] == "ABORT" and not self.checked[dev]:
|
||||
logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(True)
|
||||
bb.event.fire(bb.event.DiskFull(dev, 'disk', freeSpace, self.devDict[dev][1]), self.configuration)
|
||||
|
||||
# The free inodes, float point number
|
||||
freeInode = st.f_favail
|
||||
@@ -240,10 +237,8 @@ class diskMonitor:
|
||||
logger.error("No new tasks can be excuted since the disk space monitor action is \"STOPTASKS\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(False)
|
||||
bb.event.fire(bb.event.DiskFull(dev, 'inode', freeSpace, self.devDict[dev][1]), self.configuration)
|
||||
elif self.devDict[dev][0] == "ABORT" and not self.checked[dev]:
|
||||
logger.error("Immediately abort since the disk space monitor action is \"ABORT\"!")
|
||||
self.checked[dev] = True
|
||||
rq.finish_runqueue(True)
|
||||
bb.event.fire(bb.event.DiskFull(dev, 'inode', freeSpace, self.devDict[dev][1]), self.configuration)
|
||||
return
|
||||
|
||||
@@ -212,9 +212,9 @@ class ExportFuncsNode(AstNode):
|
||||
data.setVarFlag(calledvar, flag, data.getVarFlag(var, flag))
|
||||
|
||||
if data.getVarFlag(calledvar, "python"):
|
||||
data.setVar(var, " bb.build.exec_func('" + calledvar + "', d)\n")
|
||||
data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n")
|
||||
else:
|
||||
data.setVar(var, " " + calledvar + "\n")
|
||||
data.setVar(var, "\t" + calledvar + "\n")
|
||||
data.setVarFlag(var, 'export_func', '1')
|
||||
|
||||
class AddTaskNode(AstNode):
|
||||
|
||||
@@ -69,7 +69,7 @@ def supports(fn, d):
|
||||
return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
|
||||
|
||||
def inherit(files, fn, lineno, d):
|
||||
__inherit_cache = d.getVar('__inherit_cache') or []
|
||||
__inherit_cache = data.getVar('__inherit_cache', d) or []
|
||||
files = d.expand(files).split()
|
||||
for file in files:
|
||||
if not os.path.isabs(file) and not file.endswith(".bbclass"):
|
||||
@@ -80,7 +80,7 @@ def inherit(files, fn, lineno, d):
|
||||
__inherit_cache.append( file )
|
||||
data.setVar('__inherit_cache', __inherit_cache, d)
|
||||
include(fn, file, lineno, d, "inherit")
|
||||
__inherit_cache = d.getVar('__inherit_cache') or []
|
||||
__inherit_cache = data.getVar('__inherit_cache', d) or []
|
||||
|
||||
def get_statements(filename, absolute_filename, base_name):
|
||||
global cached_statements
|
||||
@@ -126,13 +126,13 @@ def handle(fn, d, include):
|
||||
if ext == ".bbclass":
|
||||
__classname__ = root
|
||||
classes.append(__classname__)
|
||||
__inherit_cache = d.getVar('__inherit_cache') or []
|
||||
__inherit_cache = data.getVar('__inherit_cache', d) or []
|
||||
if not fn in __inherit_cache:
|
||||
__inherit_cache.append(fn)
|
||||
data.setVar('__inherit_cache', __inherit_cache, d)
|
||||
|
||||
if include != 0:
|
||||
oldfile = d.getVar('FILE')
|
||||
oldfile = data.getVar('FILE', d)
|
||||
else:
|
||||
oldfile = None
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import logging
|
||||
import signal
|
||||
import subprocess
|
||||
import errno
|
||||
import select
|
||||
|
||||
logger = logging.getLogger('BitBake.Process')
|
||||
|
||||
@@ -70,38 +68,20 @@ def _logged_communicate(pipe, log, input):
|
||||
pipe.stdin.write(input)
|
||||
pipe.stdin.close()
|
||||
|
||||
bufsize = 512
|
||||
outdata, errdata = [], []
|
||||
rin = []
|
||||
while pipe.poll() is None:
|
||||
if pipe.stdout is not None:
|
||||
data = pipe.stdout.read(bufsize)
|
||||
if data is not None:
|
||||
outdata.append(data)
|
||||
log.write(data)
|
||||
|
||||
if pipe.stdout is not None:
|
||||
bb.utils.nonblockingfd(pipe.stdout.fileno())
|
||||
rin.append(pipe.stdout)
|
||||
if pipe.stderr is not None:
|
||||
bb.utils.nonblockingfd(pipe.stderr.fileno())
|
||||
rin.append(pipe.stderr)
|
||||
|
||||
try:
|
||||
while pipe.poll() is None:
|
||||
rlist = rin
|
||||
try:
|
||||
r,w,e = select.select (rlist, [], [])
|
||||
except OSError, e:
|
||||
if e.errno != errno.EINTR:
|
||||
raise
|
||||
|
||||
if pipe.stdout in r:
|
||||
data = pipe.stdout.read()
|
||||
if data is not None:
|
||||
outdata.append(data)
|
||||
log.write(data)
|
||||
|
||||
if pipe.stderr in r:
|
||||
data = pipe.stderr.read()
|
||||
if data is not None:
|
||||
errdata.append(data)
|
||||
log.write(data)
|
||||
finally:
|
||||
log.flush()
|
||||
if pipe.stderr is not None:
|
||||
data = pipe.stderr.read(bufsize)
|
||||
if data is not None:
|
||||
errdata.append(data)
|
||||
log.write(data)
|
||||
return ''.join(outdata), ''.join(errdata)
|
||||
|
||||
def run(cmd, input=None, log=None, **options):
|
||||
|
||||
@@ -35,8 +35,6 @@ class NoProvider(bb.BBHandledException):
|
||||
class NoRProvider(bb.BBHandledException):
|
||||
"""Exception raised when no provider of a runtime dependency can be found"""
|
||||
|
||||
class MultipleRProvider(bb.BBHandledException):
|
||||
"""Exception raised when multiple providers of a runtime dependency can be found"""
|
||||
|
||||
def findProviders(cfgData, dataCache, pkg_pn = None):
|
||||
"""
|
||||
|
||||
@@ -375,8 +375,9 @@ class RunQueueData:
|
||||
"""
|
||||
|
||||
runq_build = []
|
||||
recursivetasks = {}
|
||||
recursivetasksselfref = set()
|
||||
recursive_tdepends = {}
|
||||
runq_recrdepends = []
|
||||
tdepends_fnid = {}
|
||||
|
||||
taskData = self.taskData
|
||||
|
||||
@@ -405,10 +406,11 @@ class RunQueueData:
|
||||
depdata = taskData.build_targets[depid][0]
|
||||
if depdata is None:
|
||||
continue
|
||||
dep = taskData.fn_index[depdata]
|
||||
for taskname in tasknames:
|
||||
taskid = taskData.gettask_id_fromfnid(depdata, taskname)
|
||||
taskid = taskData.gettask_id(dep, taskname, False)
|
||||
if taskid is not None:
|
||||
depends.add(taskid)
|
||||
depends.append(taskid)
|
||||
|
||||
def add_runtime_dependencies(depids, tasknames, depends):
|
||||
for depid in depids:
|
||||
@@ -417,20 +419,15 @@ class RunQueueData:
|
||||
depdata = taskData.run_targets[depid][0]
|
||||
if depdata is None:
|
||||
continue
|
||||
dep = taskData.fn_index[depdata]
|
||||
for taskname in tasknames:
|
||||
taskid = taskData.gettask_id_fromfnid(depdata, taskname)
|
||||
taskid = taskData.gettask_id(dep, taskname, False)
|
||||
if taskid is not None:
|
||||
depends.add(taskid)
|
||||
|
||||
def add_resolved_dependencies(depids, tasknames, depends):
|
||||
for depid in depids:
|
||||
for taskname in tasknames:
|
||||
taskid = taskData.gettask_id_fromfnid(depid, taskname)
|
||||
if taskid is not None:
|
||||
depends.add(taskid)
|
||||
depends.append(taskid)
|
||||
|
||||
for task in xrange(len(taskData.tasks_name)):
|
||||
depends = set()
|
||||
depends = []
|
||||
recrdepends = []
|
||||
fnid = taskData.tasks_fnid[task]
|
||||
fn = taskData.fn_index[fnid]
|
||||
task_deps = self.dataCache.task_deps[fn]
|
||||
@@ -442,7 +439,7 @@ class RunQueueData:
|
||||
# Resolve task internal dependencies
|
||||
#
|
||||
# e.g. addtask before X after Y
|
||||
depends = set(taskData.tasks_tdepends[task])
|
||||
depends = taskData.tasks_tdepends[task]
|
||||
|
||||
# Resolve 'deptask' dependencies
|
||||
#
|
||||
@@ -457,91 +454,99 @@ class RunQueueData:
|
||||
# e.g. do_sometask[rdeptask] = "do_someothertask"
|
||||
# (makes sure sometask runs after someothertask of all RDEPENDS)
|
||||
if 'rdeptask' in task_deps and taskData.tasks_name[task] in task_deps['rdeptask']:
|
||||
tasknames = task_deps['rdeptask'][taskData.tasks_name[task]].split()
|
||||
add_runtime_dependencies(taskData.rdepids[fnid], tasknames, depends)
|
||||
taskname = task_deps['rdeptask'][taskData.tasks_name[task]]
|
||||
add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends)
|
||||
|
||||
# Resolve inter-task dependencies
|
||||
#
|
||||
# e.g. do_sometask[depends] = "targetname:do_someothertask"
|
||||
# (makes sure sometask runs after targetname's someothertask)
|
||||
if fnid not in tdepends_fnid:
|
||||
tdepends_fnid[fnid] = set()
|
||||
idepends = taskData.tasks_idepends[task]
|
||||
for (depid, idependtask) in idepends:
|
||||
if depid in taskData.build_targets:
|
||||
# Won't be in build_targets if ASSUME_PROVIDED
|
||||
depdata = taskData.build_targets[depid][0]
|
||||
if depdata is not None:
|
||||
taskid = taskData.gettask_id_fromfnid(depdata, idependtask)
|
||||
dep = taskData.fn_index[depdata]
|
||||
taskid = taskData.gettask_id(dep, idependtask, False)
|
||||
if taskid is None:
|
||||
bb.msg.fatal("RunQueue", "Task %s in %s depends upon non-existent task %s in %s" % (taskData.tasks_name[task], fn, idependtask, dep))
|
||||
depends.add(taskid)
|
||||
irdepends = taskData.tasks_irdepends[task]
|
||||
for (depid, idependtask) in irdepends:
|
||||
if depid in taskData.run_targets:
|
||||
# Won't be in run_targets if ASSUME_PROVIDED
|
||||
depdata = taskData.run_targets[depid][0]
|
||||
if depdata is not None:
|
||||
taskid = taskData.gettask_id_fromfnid(depdata, idependtask)
|
||||
if taskid is None:
|
||||
bb.msg.fatal("RunQueue", "Task %s in %s rdepends upon non-existent task %s in %s" % (taskData.tasks_name[task], fn, idependtask, dep))
|
||||
depends.add(taskid)
|
||||
depends.append(taskid)
|
||||
if depdata != fnid:
|
||||
tdepends_fnid[fnid].add(taskid)
|
||||
|
||||
# Resolve recursive 'recrdeptask' dependencies (Part A)
|
||||
|
||||
# Resolve recursive 'recrdeptask' dependencies (A)
|
||||
#
|
||||
# e.g. do_sometask[recrdeptask] = "do_someothertask"
|
||||
# (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
|
||||
# We cover the recursive part of the dependencies below
|
||||
if 'recrdeptask' in task_deps and taskData.tasks_name[task] in task_deps['recrdeptask']:
|
||||
tasknames = task_deps['recrdeptask'][taskData.tasks_name[task]].split()
|
||||
recursivetasks[task] = tasknames
|
||||
add_build_dependencies(taskData.depids[fnid], tasknames, depends)
|
||||
add_runtime_dependencies(taskData.rdepids[fnid], tasknames, depends)
|
||||
if taskData.tasks_name[task] in tasknames:
|
||||
recursivetasksselfref.add(task)
|
||||
for taskname in task_deps['recrdeptask'][taskData.tasks_name[task]].split():
|
||||
recrdepends.append(taskname)
|
||||
add_build_dependencies(taskData.depids[fnid], [taskname], depends)
|
||||
add_runtime_dependencies(taskData.rdepids[fnid], [taskname], depends)
|
||||
|
||||
# Rmove all self references
|
||||
if task in depends:
|
||||
newdep = []
|
||||
logger.debug(2, "Task %s (%s %s) contains self reference! %s", task, taskData.fn_index[taskData.tasks_fnid[task]], taskData.tasks_name[task], depends)
|
||||
for dep in depends:
|
||||
if task != dep:
|
||||
newdep.append(dep)
|
||||
depends = newdep
|
||||
|
||||
self.runq_fnid.append(taskData.tasks_fnid[task])
|
||||
self.runq_task.append(taskData.tasks_name[task])
|
||||
self.runq_depends.append(depends)
|
||||
self.runq_depends.append(set(depends))
|
||||
self.runq_revdeps.append(set())
|
||||
self.runq_hash.append("")
|
||||
|
||||
runq_build.append(0)
|
||||
runq_recrdepends.append(recrdepends)
|
||||
|
||||
# Resolve recursive 'recrdeptask' dependencies (Part B)
|
||||
#
|
||||
# Build a list of recursive cumulative dependencies for each fnid
|
||||
# We do this by fnid, since if A depends on some task in B
|
||||
# we're interested in later tasks B's fnid might have but B itself
|
||||
# doesn't depend on
|
||||
#
|
||||
# Algorithm is O(tasks) + O(tasks)*O(fnids)
|
||||
#
|
||||
reccumdepends = {}
|
||||
for task in xrange(len(self.runq_fnid)):
|
||||
fnid = self.runq_fnid[task]
|
||||
if fnid not in reccumdepends:
|
||||
if fnid in tdepends_fnid:
|
||||
reccumdepends[fnid] = tdepends_fnid[fnid]
|
||||
else:
|
||||
reccumdepends[fnid] = set()
|
||||
reccumdepends[fnid].update(self.runq_depends[task])
|
||||
for task in xrange(len(self.runq_fnid)):
|
||||
taskfnid = self.runq_fnid[task]
|
||||
for fnid in reccumdepends:
|
||||
if task in reccumdepends[fnid]:
|
||||
reccumdepends[fnid].add(task)
|
||||
if taskfnid in reccumdepends:
|
||||
reccumdepends[fnid].update(reccumdepends[taskfnid])
|
||||
|
||||
|
||||
# Resolve recursive 'recrdeptask' dependencies (B)
|
||||
#
|
||||
# e.g. do_sometask[recrdeptask] = "do_someothertask"
|
||||
# (makes sure sometask runs after someothertask of all DEPENDS, RDEPENDS and intertask dependencies, recursively)
|
||||
# We need to do this separately since we need all of self.runq_depends to be complete before this is processed
|
||||
extradeps = {}
|
||||
for task in recursivetasks:
|
||||
extradeps[task] = set(self.runq_depends[task])
|
||||
tasknames = recursivetasks[task]
|
||||
seendeps = set()
|
||||
seenfnid = []
|
||||
|
||||
def generate_recdeps(t):
|
||||
newdeps = set()
|
||||
add_resolved_dependencies([taskData.tasks_fnid[t]], tasknames, newdeps)
|
||||
extradeps[task].update(newdeps)
|
||||
seendeps.add(t)
|
||||
newdeps.add(t)
|
||||
for i in newdeps:
|
||||
for n in self.runq_depends[i]:
|
||||
if n not in seendeps:
|
||||
generate_recdeps(n)
|
||||
generate_recdeps(task)
|
||||
|
||||
# Remove circular references so that do_a[recrdeptask] = "do_a do_b" can work
|
||||
for task in recursivetasks:
|
||||
extradeps[task].difference_update(recursivetasksselfref)
|
||||
|
||||
for task in xrange(len(taskData.tasks_name)):
|
||||
# Add in extra dependencies
|
||||
if task in extradeps:
|
||||
self.runq_depends[task] = extradeps[task]
|
||||
# Remove all self references
|
||||
if task in self.runq_depends[task]:
|
||||
logger.debug(2, "Task %s (%s %s) contains self reference! %s", task, taskData.fn_index[taskData.tasks_fnid[task]], taskData.tasks_name[task], self.runq_depends[task])
|
||||
self.runq_depends[task].remove(task)
|
||||
for task in xrange(len(self.runq_fnid)):
|
||||
if len(runq_recrdepends[task]) > 0:
|
||||
taskfnid = self.runq_fnid[task]
|
||||
for dep in reccumdepends[taskfnid]:
|
||||
# Ignore self references
|
||||
if dep == task:
|
||||
continue
|
||||
for taskname in runq_recrdepends[task]:
|
||||
if taskData.tasks_name[dep] == taskname:
|
||||
self.runq_depends[task].add(dep)
|
||||
|
||||
# Step B - Mark all active tasks
|
||||
#
|
||||
@@ -700,27 +705,11 @@ class RunQueueData:
|
||||
continue
|
||||
self.runq_setscene.append(task)
|
||||
|
||||
def invalidate_task(fn, taskname, error_nostamp):
|
||||
taskdep = self.dataCache.task_deps[fn]
|
||||
if 'nostamp' in taskdep and taskname in taskdep['nostamp']:
|
||||
if error_nostamp:
|
||||
bb.fatal("Task %s is marked nostamp, cannot invalidate this task" % taskname)
|
||||
else:
|
||||
bb.debug(1, "Task %s is marked nostamp, cannot invalidate this task" % taskname)
|
||||
else:
|
||||
logger.verbose("Invalidate task %s, %s", taskname, fn)
|
||||
bb.parse.siggen.invalidate_task(taskname, self.dataCache, fn)
|
||||
|
||||
# Invalidate task if force mode active
|
||||
if self.cooker.configuration.force:
|
||||
for (fn, target) in self.target_pairs:
|
||||
invalidate_task(fn, target, False)
|
||||
|
||||
# Invalidate task if invalidate mode active
|
||||
if self.cooker.configuration.invalidate_stamp:
|
||||
for (fn, target) in self.target_pairs:
|
||||
for st in self.cooker.configuration.invalidate_stamp.split(','):
|
||||
invalidate_task(fn, "do_%s" % st, True)
|
||||
logger.verbose("Invalidate task %s, %s", target, fn)
|
||||
bb.parse.siggen.invalidate_task(target, self.dataCache, fn)
|
||||
|
||||
# Interate over the task list and call into the siggen code
|
||||
dealtwith = set()
|
||||
@@ -792,7 +781,101 @@ class RunQueue:
|
||||
|
||||
self.rqexe = None
|
||||
|
||||
def check_stamp_task(self, task, taskname = None, recurse = False, cache = None):
|
||||
def check_stamps(self):
|
||||
unchecked = {}
|
||||
current = []
|
||||
notcurrent = []
|
||||
buildable = []
|
||||
|
||||
if self.stamppolicy == "perfile":
|
||||
fulldeptree = False
|
||||
else:
|
||||
fulldeptree = True
|
||||
stampwhitelist = []
|
||||
if self.stamppolicy == "whitelist":
|
||||
stampwhitelist = self.rqdata.stampfnwhitelist
|
||||
|
||||
for task in xrange(len(self.rqdata.runq_fnid)):
|
||||
unchecked[task] = ""
|
||||
if len(self.rqdata.runq_depends[task]) == 0:
|
||||
buildable.append(task)
|
||||
|
||||
def check_buildable(self, task, buildable):
|
||||
for revdep in self.rqdata.runq_revdeps[task]:
|
||||
alldeps = 1
|
||||
for dep in self.rqdata.runq_depends[revdep]:
|
||||
if dep in unchecked:
|
||||
alldeps = 0
|
||||
if alldeps == 1:
|
||||
if revdep in unchecked:
|
||||
buildable.append(revdep)
|
||||
|
||||
for task in xrange(len(self.rqdata.runq_fnid)):
|
||||
if task not in unchecked:
|
||||
continue
|
||||
fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
|
||||
taskname = self.rqdata.runq_task[task]
|
||||
stampfile = bb.build.stampfile(taskname, self.rqdata.dataCache, fn)
|
||||
# If the stamp is missing its not current
|
||||
if not os.access(stampfile, os.F_OK):
|
||||
del unchecked[task]
|
||||
notcurrent.append(task)
|
||||
check_buildable(self, task, buildable)
|
||||
continue
|
||||
# If its a 'nostamp' task, it's not current
|
||||
taskdep = self.rqdata.dataCache.task_deps[fn]
|
||||
if 'nostamp' in taskdep and task in taskdep['nostamp']:
|
||||
del unchecked[task]
|
||||
notcurrent.append(task)
|
||||
check_buildable(self, task, buildable)
|
||||
continue
|
||||
|
||||
while (len(buildable) > 0):
|
||||
nextbuildable = []
|
||||
for task in buildable:
|
||||
if task in unchecked:
|
||||
fn = self.taskData.fn_index[self.rqdata.runq_fnid[task]]
|
||||
taskname = self.rqdata.runq_task[task]
|
||||
stampfile = bb.build.stampfile(taskname, self.rqdata.dataCache, fn)
|
||||
iscurrent = True
|
||||
|
||||
t1 = os.stat(stampfile)[stat.ST_MTIME]
|
||||
for dep in self.rqdata.runq_depends[task]:
|
||||
if iscurrent:
|
||||
fn2 = self.taskData.fn_index[self.rqdata.runq_fnid[dep]]
|
||||
taskname2 = self.rqdata.runq_task[dep]
|
||||
stampfile2 = bb.build.stampfile(taskname2, self.rqdata.dataCache, fn2)
|
||||
if fn == fn2 or (fulldeptree and fn2 not in stampwhitelist):
|
||||
if dep in notcurrent:
|
||||
iscurrent = False
|
||||
else:
|
||||
t2 = os.stat(stampfile2)[stat.ST_MTIME]
|
||||
if t1 < t2:
|
||||
iscurrent = False
|
||||
del unchecked[task]
|
||||
if iscurrent:
|
||||
current.append(task)
|
||||
else:
|
||||
notcurrent.append(task)
|
||||
|
||||
check_buildable(self, task, nextbuildable)
|
||||
|
||||
buildable = nextbuildable
|
||||
|
||||
#for task in range(len(self.runq_fnid)):
|
||||
# fn = self.taskData.fn_index[self.runq_fnid[task]]
|
||||
# taskname = self.runq_task[task]
|
||||
# print "%s %s.%s" % (task, taskname, fn)
|
||||
|
||||
#print "Unchecked: %s" % unchecked
|
||||
#print "Current: %s" % current
|
||||
#print "Not current: %s" % notcurrent
|
||||
|
||||
if len(unchecked) > 0:
|
||||
bb.msg.fatal("RunQueue", "check_stamps fatal internal error")
|
||||
return current
|
||||
|
||||
def check_stamp_task(self, task, taskname = None, recurse = False):
|
||||
def get_timestamp(f):
|
||||
try:
|
||||
if not os.access(f, os.F_OK):
|
||||
@@ -828,9 +911,6 @@ class RunQueue:
|
||||
if taskname != "do_setscene" and taskname.endswith("_setscene"):
|
||||
return True
|
||||
|
||||
if cache is None:
|
||||
cache = {}
|
||||
|
||||
iscurrent = True
|
||||
t1 = get_timestamp(stampfile)
|
||||
for dep in self.rqdata.runq_depends[task]:
|
||||
@@ -851,18 +931,10 @@ class RunQueue:
|
||||
logger.debug(2, 'Stampfile %s < %s', stampfile, stampfile2)
|
||||
iscurrent = False
|
||||
if recurse and iscurrent:
|
||||
if dep in cache:
|
||||
iscurrent = cache[dep]
|
||||
if not iscurrent:
|
||||
logger.debug(2, 'Stampfile for dependency %s:%s invalid (cached)' % (fn2, taskname2))
|
||||
else:
|
||||
iscurrent = self.check_stamp_task(dep, recurse=True, cache=cache)
|
||||
cache[dep] = iscurrent
|
||||
if recurse:
|
||||
cache[task] = iscurrent
|
||||
iscurrent = self.check_stamp_task(dep, recurse=True)
|
||||
return iscurrent
|
||||
|
||||
def _execute_runqueue(self):
|
||||
def execute_runqueue(self):
|
||||
"""
|
||||
Run the tasks in a queue prepared by rqdata.prepare()
|
||||
Upon failure, optionally try to recover the build using any alternate providers
|
||||
@@ -926,17 +998,6 @@ class RunQueue:
|
||||
# Loop
|
||||
return retval
|
||||
|
||||
def execute_runqueue(self):
|
||||
# Catch unexpected exceptions and ensure we exit when an error occurs, not loop.
|
||||
try:
|
||||
return self._execute_runqueue()
|
||||
except bb.runqueue.TaskFailure:
|
||||
raise
|
||||
except:
|
||||
logger.error("An uncaught exception occured in runqueue, please see the failure below:")
|
||||
self.state = runQueueComplete
|
||||
raise
|
||||
|
||||
def finish_runqueue(self, now = False):
|
||||
if not self.rqexe:
|
||||
return
|
||||
@@ -980,36 +1041,23 @@ class RunQueueExecute:
|
||||
self.build_stamps = {}
|
||||
self.failed_fnids = []
|
||||
|
||||
self.stampcache = {}
|
||||
|
||||
def runqueue_process_waitpid(self):
|
||||
"""
|
||||
Return none is there are no processes awaiting result collection, otherwise
|
||||
collect the process exit codes and close the information pipe.
|
||||
"""
|
||||
pid, status = os.waitpid(-1, os.WNOHANG)
|
||||
if pid == 0 or os.WIFSTOPPED(status):
|
||||
result = os.waitpid(-1, os.WNOHANG)
|
||||
if result[0] == 0 and result[1] == 0:
|
||||
return None
|
||||
|
||||
if os.WIFEXITED(status):
|
||||
status = os.WEXITSTATUS(status)
|
||||
elif os.WIFSIGNALED(status):
|
||||
# Per shell conventions for $?, when a process exits due to
|
||||
# a signal, we return an exit code of 128 + SIGNUM
|
||||
status = 128 + os.WTERMSIG(status)
|
||||
|
||||
task = self.build_pids[pid]
|
||||
del self.build_pids[pid]
|
||||
|
||||
self.build_pipes[pid].close()
|
||||
del self.build_pipes[pid]
|
||||
|
||||
# self.build_stamps[pid] may not exist when use shared work directory.
|
||||
if pid in self.build_stamps:
|
||||
del self.build_stamps[pid]
|
||||
|
||||
if status != 0:
|
||||
self.task_fail(task, status)
|
||||
task = self.build_pids[result[0]]
|
||||
del self.build_pids[result[0]]
|
||||
self.build_pipes[result[0]].close()
|
||||
del self.build_pipes[result[0]]
|
||||
# self.build_stamps[result[0]] may not exist when use shared work directory.
|
||||
if result[0] in self.build_stamps.keys():
|
||||
del self.build_stamps[result[0]]
|
||||
if result[1] != 0:
|
||||
self.task_fail(task, result[1]>>8)
|
||||
else:
|
||||
self.task_complete(task)
|
||||
return True
|
||||
@@ -1116,6 +1164,8 @@ class RunQueueExecute:
|
||||
os.umask(umask)
|
||||
|
||||
self.cooker.configuration.data.setVar("BB_WORKERCONTEXT", "1")
|
||||
self.cooker.configuration.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY", self)
|
||||
self.cooker.configuration.data.setVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2", fn)
|
||||
bb.parse.siggen.set_taskdata(self.rqdata.hashes, self.rqdata.hash_deps)
|
||||
ret = 0
|
||||
try:
|
||||
@@ -1173,8 +1223,6 @@ class RunQueueExecuteTasks(RunQueueExecute):
|
||||
|
||||
self.stats = RunQueueStats(len(self.rqdata.runq_fnid))
|
||||
|
||||
self.stampcache = {}
|
||||
|
||||
# Mark initial buildable tasks
|
||||
for task in xrange(self.stats.total):
|
||||
self.runq_running.append(0)
|
||||
@@ -1183,7 +1231,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
|
||||
self.runq_buildable.append(1)
|
||||
else:
|
||||
self.runq_buildable.append(0)
|
||||
if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
|
||||
if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
|
||||
self.rq.scenequeue_covered.add(task)
|
||||
|
||||
found = True
|
||||
@@ -1194,7 +1242,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
|
||||
continue
|
||||
logger.debug(1, 'Considering %s (%s): %s' % (task, self.rqdata.get_user_idstring(task), str(self.rqdata.runq_revdeps[task])))
|
||||
|
||||
if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
|
||||
if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
|
||||
ok = True
|
||||
for revdep in self.rqdata.runq_revdeps[task]:
|
||||
if self.rqdata.runq_fnid[task] != self.rqdata.runq_fnid[revdep]:
|
||||
@@ -1211,30 +1259,9 @@ class RunQueueExecuteTasks(RunQueueExecute):
|
||||
# Allow the metadata to elect for setscene tasks to run anyway
|
||||
covered_remove = set()
|
||||
if self.rq.setsceneverify:
|
||||
invalidtasks = []
|
||||
for task in xrange(len(self.rqdata.runq_task)):
|
||||
fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
|
||||
taskname = self.rqdata.runq_task[task]
|
||||
taskdep = self.rqdata.dataCache.task_deps[fn]
|
||||
|
||||
if 'noexec' in taskdep and taskname in taskdep['noexec']:
|
||||
continue
|
||||
if self.rq.check_stamp_task(task, taskname + "_setscene", cache=self.stampcache):
|
||||
logger.debug(2, 'Setscene stamp current for task %s(%s)', task, self.rqdata.get_user_idstring(task))
|
||||
continue
|
||||
if self.rq.check_stamp_task(task, taskname, recurse = True, cache=self.stampcache):
|
||||
logger.debug(2, 'Normal stamp current for task %s(%s)', task, self.rqdata.get_user_idstring(task))
|
||||
continue
|
||||
invalidtasks.append(task)
|
||||
|
||||
call = self.rq.setsceneverify + "(covered, tasknames, fnids, fns, d, invalidtasks=invalidtasks)"
|
||||
call2 = self.rq.setsceneverify + "(covered, tasknames, fnids, fns, d)"
|
||||
locs = { "covered" : self.rq.scenequeue_covered, "tasknames" : self.rqdata.runq_task, "fnids" : self.rqdata.runq_fnid, "fns" : self.rqdata.taskData.fn_index, "d" : self.cooker.configuration.data, "invalidtasks" : invalidtasks }
|
||||
# Backwards compatibility with older versions without invalidtasks
|
||||
try:
|
||||
covered_remove = bb.utils.better_eval(call, locs)
|
||||
except TypeError:
|
||||
covered_remove = bb.utils.better_eval(call2, locs)
|
||||
call = self.rq.setsceneverify + "(covered, tasknames, fnids, fns, d)"
|
||||
locs = { "covered" : self.rq.scenequeue_covered, "tasknames" : self.rqdata.runq_task, "fnids" : self.rqdata.runq_fnid, "fns" : self.rqdata.taskData.fn_index, "d" : self.cooker.configuration.data }
|
||||
covered_remove = bb.utils.better_eval(call, locs)
|
||||
|
||||
for task in covered_remove:
|
||||
fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[task]]
|
||||
@@ -1346,7 +1373,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
|
||||
self.task_skip(task)
|
||||
return True
|
||||
|
||||
if self.rq.check_stamp_task(task, taskname, cache=self.stampcache):
|
||||
if self.rq.check_stamp_task(task, taskname):
|
||||
logger.debug(2, "Stamp current task %s (%s)", task,
|
||||
self.rqdata.get_user_idstring(task))
|
||||
self.task_skip(task)
|
||||
@@ -1487,7 +1514,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
dep = self.rqdata.taskData.fn_index[depdata]
|
||||
taskid = self.rqdata.get_task_id(self.rqdata.taskData.getfn_id(dep), idependtask.replace("_setscene", ""))
|
||||
if taskid is None:
|
||||
bb.msg.fatal("RunQueue", "Task %s:%s depends upon non-existent task %s:%s" % (self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[realid]], self.rqdata.taskData.tasks_name[realid], dep, idependtask))
|
||||
bb.msg.fatal("RunQueue", "Task %s depends upon non-existent task %s:%s" % (self.rqdata.taskData.tasks_name[realid], dep, idependtask))
|
||||
|
||||
sq_revdeps_squash[self.rqdata.runq_setscene.index(task)].add(self.rqdata.runq_setscene.index(taskid))
|
||||
# Have to zero this to avoid circular dependencies
|
||||
@@ -1530,18 +1557,12 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
bb.build.make_stamp(taskname + "_setscene", self.rqdata.dataCache, fn)
|
||||
continue
|
||||
|
||||
if self.rq.check_stamp_task(realtask, taskname + "_setscene", cache=self.stampcache):
|
||||
if self.rq.check_stamp_task(realtask, taskname + "_setscene"):
|
||||
logger.debug(2, 'Setscene stamp current for task %s(%s)', task, self.rqdata.get_user_idstring(realtask))
|
||||
stamppresent.append(task)
|
||||
self.task_skip(task)
|
||||
continue
|
||||
|
||||
if self.rq.check_stamp_task(realtask, taskname, recurse = True, cache=self.stampcache):
|
||||
logger.debug(2, 'Normal stamp current for task %s(%s)', task, self.rqdata.get_user_idstring(realtask))
|
||||
stamppresent.append(task)
|
||||
self.task_skip(task)
|
||||
continue
|
||||
|
||||
sq_fn.append(fn)
|
||||
sq_hashfn.append(self.rqdata.dataCache.hashfn[fn])
|
||||
sq_hash.append(self.rqdata.runq_hash[realtask])
|
||||
@@ -1629,7 +1650,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
fn = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[realtask]]
|
||||
|
||||
taskname = self.rqdata.runq_task[realtask] + "_setscene"
|
||||
if self.rq.check_stamp_task(realtask, self.rqdata.runq_task[realtask], recurse = True, cache=self.stampcache):
|
||||
if self.rq.check_stamp_task(realtask, self.rqdata.runq_task[realtask], recurse = True):
|
||||
logger.debug(2, 'Stamp for underlying task %s(%s) is current, so skipping setscene variant',
|
||||
task, self.rqdata.get_user_idstring(realtask))
|
||||
self.task_failoutright(task)
|
||||
@@ -1641,7 +1662,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
self.task_failoutright(task)
|
||||
return True
|
||||
|
||||
if self.rq.check_stamp_task(realtask, taskname, cache=self.stampcache):
|
||||
if self.rq.check_stamp_task(realtask, taskname):
|
||||
logger.debug(2, 'Setscene stamp current task %s(%s), so skip it and its dependencies',
|
||||
task, self.rqdata.get_user_idstring(realtask))
|
||||
self.task_skip(task)
|
||||
@@ -1672,9 +1693,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
self.rq.scenequeue_covered = set()
|
||||
for task in oldcovered:
|
||||
self.rq.scenequeue_covered.add(self.rqdata.runq_setscene[task])
|
||||
self.rq.scenequeue_notcovered = set()
|
||||
for task in self.scenequeue_notcovered:
|
||||
self.rq.scenequeue_notcovered.add(self.rqdata.runq_setscene[task])
|
||||
|
||||
logger.debug(1, 'We can skip tasks %s', sorted(self.rq.scenequeue_covered))
|
||||
|
||||
@@ -1758,6 +1776,15 @@ class runQueueTaskCompleted(runQueueEvent):
|
||||
Event notifing a task completed
|
||||
"""
|
||||
|
||||
def check_stamp_fn(fn, taskname, d):
|
||||
rqexe = d.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY")
|
||||
fn = d.getVar("__RUNQUEUE_DO_NOT_USE_EXTERNALLY2")
|
||||
fnid = rqexe.rqdata.taskData.getfn_id(fn)
|
||||
taskid = rqexe.rqdata.get_task_id(fnid, taskname)
|
||||
if taskid is not None:
|
||||
return rqexe.rq.check_stamp_task(taskid)
|
||||
return None
|
||||
|
||||
class runQueuePipe():
|
||||
"""
|
||||
Abstraction for a pipe between a worker thread and the server
|
||||
@@ -1765,7 +1792,7 @@ class runQueuePipe():
|
||||
def __init__(self, pipein, pipeout, d):
|
||||
self.input = pipein
|
||||
pipeout.close()
|
||||
bb.utils.nonblockingfd(self.input)
|
||||
fcntl.fcntl(self.input, fcntl.F_SETFL, fcntl.fcntl(self.input, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||
self.queue = ""
|
||||
self.d = d
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import hashlib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
import bb.data
|
||||
|
||||
logger = logging.getLogger('BitBake.SigGen')
|
||||
@@ -65,7 +64,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
self.taskhash = {}
|
||||
self.taskdeps = {}
|
||||
self.runtaskdeps = {}
|
||||
self.file_checksum_values = {}
|
||||
self.gendeps = {}
|
||||
self.lookupcache = {}
|
||||
self.pkgnameextract = re.compile("(?P<fn>.*)\..*")
|
||||
@@ -113,10 +111,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
data = data + dep
|
||||
if dep in lookupcache:
|
||||
var = lookupcache[dep]
|
||||
elif dep[-1] == ']':
|
||||
vf = dep[:-1].split('[')
|
||||
var = d.getVarFlag(vf[0], vf[1], False)
|
||||
lookupcache[dep] = var
|
||||
else:
|
||||
var = d.getVar(dep, False)
|
||||
lookupcache[dep] = var
|
||||
@@ -171,7 +165,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
k = fn + "." + task
|
||||
data = dataCache.basetaskhash[k]
|
||||
self.runtaskdeps[k] = []
|
||||
self.file_checksum_values[k] = {}
|
||||
recipename = dataCache.pkg_fn[fn]
|
||||
for dep in sorted(deps, key=clean_basepath):
|
||||
depname = dataCache.pkg_fn[self.pkgnameextract.search(dep).group('fn')]
|
||||
@@ -182,12 +175,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
data = data + self.taskhash[dep]
|
||||
self.runtaskdeps[k].append(dep)
|
||||
|
||||
if task in dataCache.file_checksums[fn]:
|
||||
checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename)
|
||||
for (f,cs) in checksums:
|
||||
self.file_checksum_values[k][f] = cs
|
||||
data = data + cs
|
||||
|
||||
taint = self.read_taint(fn, task, dataCache.stamp[fn])
|
||||
if taint:
|
||||
data = data + taint
|
||||
@@ -228,7 +215,6 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
|
||||
if runtime and k in self.taskhash:
|
||||
data['runtaskdeps'] = self.runtaskdeps[k]
|
||||
data['file_checksum_values'] = self.file_checksum_values[k]
|
||||
data['runtaskhashes'] = {}
|
||||
for dep in data['runtaskdeps']:
|
||||
data['runtaskhashes'][dep] = self.taskhash[dep]
|
||||
@@ -237,20 +223,9 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
if taint:
|
||||
data['taint'] = taint
|
||||
|
||||
fd, tmpfile = tempfile.mkstemp(dir=os.path.dirname(sigfile), prefix="sigtask.")
|
||||
try:
|
||||
with os.fdopen(fd, "wb") as stream:
|
||||
p = pickle.dump(data, stream, -1)
|
||||
stream.flush()
|
||||
os.fsync(fd)
|
||||
os.chmod(tmpfile, 0664)
|
||||
os.rename(tmpfile, sigfile)
|
||||
except (OSError, IOError), err:
|
||||
try:
|
||||
os.unlink(tmpfile)
|
||||
except OSError:
|
||||
pass
|
||||
raise err
|
||||
p = pickle.Pickler(file(sigfile, "wb"), -1)
|
||||
p.dump(data)
|
||||
|
||||
|
||||
def dump_sigs(self, dataCache):
|
||||
for fn in self.taskdeps:
|
||||
@@ -302,9 +277,9 @@ def clean_basepaths(a):
|
||||
return b
|
||||
|
||||
def compare_sigfiles(a, b):
|
||||
p1 = pickle.Unpickler(open(a, "rb"))
|
||||
p1 = pickle.Unpickler(file(a, "rb"))
|
||||
a_data = p1.load()
|
||||
p2 = pickle.Unpickler(open(b, "rb"))
|
||||
p2 = pickle.Unpickler(file(b, "rb"))
|
||||
b_data = p2.load()
|
||||
|
||||
def dict_diff(a, b, whitelist=set()):
|
||||
@@ -354,18 +329,6 @@ def compare_sigfiles(a, b):
|
||||
for dep in changed:
|
||||
print "Variable %s value changed from %s to %s" % (dep, a_data['varvals'][dep], b_data['varvals'][dep])
|
||||
|
||||
changed, added, removed = dict_diff(a_data['file_checksum_values'], b_data['file_checksum_values'])
|
||||
if changed:
|
||||
for f in changed:
|
||||
print "Checksum for file %s changed from %s to %s" % (f, a_data['file_checksum_values'][f], b_data['file_checksum_values'][f])
|
||||
if added:
|
||||
for f in added:
|
||||
print "Dependency on checksum of file %s was added" % (f)
|
||||
if removed:
|
||||
for f in removed:
|
||||
print "Dependency on checksum of file %s was removed" % (f)
|
||||
|
||||
|
||||
if 'runtaskhashes' in a_data and 'runtaskhashes' in b_data:
|
||||
a = clean_basepaths(a_data['runtaskhashes'])
|
||||
b = clean_basepaths(b_data['runtaskhashes'])
|
||||
@@ -394,15 +357,13 @@ def compare_sigfiles(a, b):
|
||||
for dep in changed:
|
||||
print "Hash for dependent task %s changed from %s to %s" % (dep, a[dep], b[dep])
|
||||
|
||||
|
||||
a_taint = a_data.get('taint', None)
|
||||
b_taint = b_data.get('taint', None)
|
||||
if a_taint != b_taint:
|
||||
print "Taint (by forced/invalidated task) changed from %s to %s" % (a_taint, b_taint)
|
||||
|
||||
|
||||
def dump_sigfile(a):
|
||||
p1 = pickle.Unpickler(open(a, "rb"))
|
||||
p1 = pickle.Unpickler(file(a, "rb"))
|
||||
a_data = p1.load()
|
||||
|
||||
print "basewhitelist: %s" % (a_data['basewhitelist'])
|
||||
@@ -422,9 +383,6 @@ def dump_sigfile(a):
|
||||
if 'runtaskdeps' in a_data:
|
||||
print "Tasks this task depends on: %s" % (a_data['runtaskdeps'])
|
||||
|
||||
if 'file_checksum_values' in a_data:
|
||||
print "This task depends on the checksums of files: %s" % (a_data['file_checksum_values'])
|
||||
|
||||
if 'runtaskhashes' in a_data:
|
||||
for dep in a_data['runtaskhashes']:
|
||||
print "Hash for dependent task %s is %s" % (dep, a_data['runtaskhashes'][dep])
|
||||
|
||||
@@ -55,7 +55,6 @@ class TaskData:
|
||||
self.tasks_name = []
|
||||
self.tasks_tdepends = []
|
||||
self.tasks_idepends = []
|
||||
self.tasks_irdepends = []
|
||||
# Cache to speed up task ID lookups
|
||||
self.tasks_lookup = {}
|
||||
|
||||
@@ -116,16 +115,6 @@ class TaskData:
|
||||
ids.append(self.tasks_lookup[fnid][task])
|
||||
return ids
|
||||
|
||||
def gettask_id_fromfnid(self, fnid, task):
|
||||
"""
|
||||
Return an ID number for the task matching fnid and task.
|
||||
"""
|
||||
if fnid in self.tasks_lookup:
|
||||
if task in self.tasks_lookup[fnid]:
|
||||
return self.tasks_lookup[fnid][task]
|
||||
|
||||
return None
|
||||
|
||||
def gettask_id(self, fn, task, create = True):
|
||||
"""
|
||||
Return an ID number for the task matching fn and task.
|
||||
@@ -145,7 +134,6 @@ class TaskData:
|
||||
self.tasks_fnid.append(fnid)
|
||||
self.tasks_tdepends.append([])
|
||||
self.tasks_idepends.append([])
|
||||
self.tasks_irdepends.append([])
|
||||
|
||||
listid = len(self.tasks_name) - 1
|
||||
|
||||
@@ -190,15 +178,6 @@ class TaskData:
|
||||
bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'depends' should be specified in the form 'packagename:task'" % (fn, dep))
|
||||
ids.append(((self.getbuild_id(dep.split(":")[0])), dep.split(":")[1]))
|
||||
self.tasks_idepends[taskid].extend(ids)
|
||||
if 'rdepends' in task_deps and task in task_deps['rdepends']:
|
||||
ids = []
|
||||
for dep in task_deps['rdepends'][task].split():
|
||||
if dep:
|
||||
if ":" not in dep:
|
||||
bb.msg.fatal("TaskData", "Error for %s, dependency %s does not contain ':' character\n. Task 'rdepends' should be specified in the form 'packagename:task'" % (fn, dep))
|
||||
ids.append(((self.getrun_id(dep.split(":")[0])), dep.split(":")[1]))
|
||||
self.tasks_irdepends[taskid].extend(ids)
|
||||
|
||||
|
||||
# Work out build dependencies
|
||||
if not fnid in self.depids:
|
||||
@@ -482,7 +461,6 @@ class TaskData:
|
||||
providers_list.append(dataCache.pkg_fn[fn])
|
||||
bb.event.fire(bb.event.MultipleProviders(item, providers_list, runtime=True), cfgData)
|
||||
self.consider_msgs_cache.append(item)
|
||||
raise bb.providers.MultipleRProvider(item)
|
||||
|
||||
# run through the list until we find one that we can build
|
||||
for fn in eligible:
|
||||
@@ -555,11 +533,6 @@ class TaskData:
|
||||
dependees = self.get_rdependees(targetid)
|
||||
for fnid in dependees:
|
||||
self.fail_fnid(fnid, missing_list)
|
||||
for taskid in xrange(len(self.tasks_irdepends)):
|
||||
irdepends = self.tasks_irdepends[taskid]
|
||||
for (idependid, idependtask) in irdepends:
|
||||
if idependid == targetid:
|
||||
self.fail_fnid(self.tasks_fnid[taskid], missing_list)
|
||||
|
||||
def add_unresolved(self, cfgData, dataCache):
|
||||
"""
|
||||
@@ -581,7 +554,7 @@ class TaskData:
|
||||
try:
|
||||
self.add_rprovider(cfgData, dataCache, target)
|
||||
added = added + 1
|
||||
except (bb.providers.NoRProvider, bb.providers.MultipleRProvider):
|
||||
except bb.providers.NoRProvider:
|
||||
self.remove_runtarget(self.getrun_id(target))
|
||||
logger.debug(1, "Resolved " + str(added) + " extra dependencies")
|
||||
if added == 0:
|
||||
|
||||
@@ -1,369 +0,0 @@
|
||||
#
|
||||
# BitBake Test for codeparser.py
|
||||
#
|
||||
# Copyright (C) 2010 Chris Larson
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import logging
|
||||
import bb
|
||||
|
||||
logger = logging.getLogger('BitBake.TestCodeParser')
|
||||
|
||||
import bb.data
|
||||
|
||||
class ReferenceTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
|
||||
def setEmptyVars(self, varlist):
|
||||
for k in varlist:
|
||||
self.d.setVar(k, "")
|
||||
|
||||
def setValues(self, values):
|
||||
for k, v in values.items():
|
||||
self.d.setVar(k, v)
|
||||
|
||||
def assertReferences(self, refs):
|
||||
self.assertEqual(self.references, refs)
|
||||
|
||||
def assertExecs(self, execs):
|
||||
self.assertEqual(self.execs, execs)
|
||||
|
||||
class VariableReferenceTest(ReferenceTest):
|
||||
|
||||
def parseExpression(self, exp):
|
||||
parsedvar = self.d.expandWithRefs(exp, None)
|
||||
self.references = parsedvar.references
|
||||
|
||||
def test_simple_reference(self):
|
||||
self.setEmptyVars(["FOO"])
|
||||
self.parseExpression("${FOO}")
|
||||
self.assertReferences(set(["FOO"]))
|
||||
|
||||
def test_nested_reference(self):
|
||||
self.setEmptyVars(["BAR"])
|
||||
self.d.setVar("FOO", "BAR")
|
||||
self.parseExpression("${${FOO}}")
|
||||
self.assertReferences(set(["FOO", "BAR"]))
|
||||
|
||||
def test_python_reference(self):
|
||||
self.setEmptyVars(["BAR"])
|
||||
self.parseExpression("${@bb.data.getVar('BAR', d, True) + 'foo'}")
|
||||
self.assertReferences(set(["BAR"]))
|
||||
|
||||
class ShellReferenceTest(ReferenceTest):
|
||||
|
||||
def parseExpression(self, exp):
|
||||
parsedvar = self.d.expandWithRefs(exp, None)
|
||||
parser = bb.codeparser.ShellParser("ParserTest", logger)
|
||||
parser.parse_shell(parsedvar.value)
|
||||
|
||||
self.references = parsedvar.references
|
||||
self.execs = parser.execs
|
||||
|
||||
def test_quotes_inside_assign(self):
|
||||
self.parseExpression('foo=foo"bar"baz')
|
||||
self.assertReferences(set([]))
|
||||
|
||||
def test_quotes_inside_arg(self):
|
||||
self.parseExpression('sed s#"bar baz"#"alpha beta"#g')
|
||||
self.assertExecs(set(["sed"]))
|
||||
|
||||
def test_arg_continuation(self):
|
||||
self.parseExpression("sed -i -e s,foo,bar,g \\\n *.pc")
|
||||
self.assertExecs(set(["sed"]))
|
||||
|
||||
def test_dollar_in_quoted(self):
|
||||
self.parseExpression('sed -i -e "foo$" *.pc')
|
||||
self.assertExecs(set(["sed"]))
|
||||
|
||||
def test_quotes_inside_arg_continuation(self):
|
||||
self.setEmptyVars(["bindir", "D", "libdir"])
|
||||
self.parseExpression("""
|
||||
sed -i -e s#"moc_location=.*$"#"moc_location=${bindir}/moc4"# \\
|
||||
-e s#"uic_location=.*$"#"uic_location=${bindir}/uic4"# \\
|
||||
${D}${libdir}/pkgconfig/*.pc
|
||||
""")
|
||||
self.assertReferences(set(["bindir", "D", "libdir"]))
|
||||
|
||||
def test_assign_subshell_expansion(self):
|
||||
self.parseExpression("foo=$(echo bar)")
|
||||
self.assertExecs(set(["echo"]))
|
||||
|
||||
def test_shell_unexpanded(self):
|
||||
self.setEmptyVars(["QT_BASE_NAME"])
|
||||
self.parseExpression('echo "${QT_BASE_NAME}"')
|
||||
self.assertExecs(set(["echo"]))
|
||||
self.assertReferences(set(["QT_BASE_NAME"]))
|
||||
|
||||
def test_incomplete_varexp_single_quotes(self):
|
||||
self.parseExpression("sed -i -e 's:IP{:I${:g' $pc")
|
||||
self.assertExecs(set(["sed"]))
|
||||
|
||||
|
||||
def test_until(self):
|
||||
self.parseExpression("until false; do echo true; done")
|
||||
self.assertExecs(set(["false", "echo"]))
|
||||
self.assertReferences(set())
|
||||
|
||||
def test_case(self):
|
||||
self.parseExpression("""
|
||||
case $foo in
|
||||
*)
|
||||
bar
|
||||
;;
|
||||
esac
|
||||
""")
|
||||
self.assertExecs(set(["bar"]))
|
||||
self.assertReferences(set())
|
||||
|
||||
def test_assign_exec(self):
|
||||
self.parseExpression("a=b c='foo bar' alpha 1 2 3")
|
||||
self.assertExecs(set(["alpha"]))
|
||||
|
||||
def test_redirect_to_file(self):
|
||||
self.setEmptyVars(["foo"])
|
||||
self.parseExpression("echo foo >${foo}/bar")
|
||||
self.assertExecs(set(["echo"]))
|
||||
self.assertReferences(set(["foo"]))
|
||||
|
||||
def test_heredoc(self):
|
||||
self.setEmptyVars(["theta"])
|
||||
self.parseExpression("""
|
||||
cat <<END
|
||||
alpha
|
||||
beta
|
||||
${theta}
|
||||
END
|
||||
""")
|
||||
self.assertReferences(set(["theta"]))
|
||||
|
||||
def test_redirect_from_heredoc(self):
|
||||
v = ["B", "SHADOW_MAILDIR", "SHADOW_MAILFILE", "SHADOW_UTMPDIR", "SHADOW_LOGDIR", "bindir"]
|
||||
self.setEmptyVars(v)
|
||||
self.parseExpression("""
|
||||
cat <<END >${B}/cachedpaths
|
||||
shadow_cv_maildir=${SHADOW_MAILDIR}
|
||||
shadow_cv_mailfile=${SHADOW_MAILFILE}
|
||||
shadow_cv_utmpdir=${SHADOW_UTMPDIR}
|
||||
shadow_cv_logdir=${SHADOW_LOGDIR}
|
||||
shadow_cv_passwd_dir=${bindir}
|
||||
END
|
||||
""")
|
||||
self.assertReferences(set(v))
|
||||
self.assertExecs(set(["cat"]))
|
||||
|
||||
# def test_incomplete_command_expansion(self):
|
||||
# self.assertRaises(reftracker.ShellSyntaxError, reftracker.execs,
|
||||
# bbvalue.shparse("cp foo`", self.d), self.d)
|
||||
|
||||
# def test_rogue_dollarsign(self):
|
||||
# self.setValues({"D" : "/tmp"})
|
||||
# self.parseExpression("install -d ${D}$")
|
||||
# self.assertReferences(set(["D"]))
|
||||
# self.assertExecs(set(["install"]))
|
||||
|
||||
|
||||
class PythonReferenceTest(ReferenceTest):
|
||||
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
if hasattr(bb.utils, "_context"):
|
||||
self.context = bb.utils._context
|
||||
else:
|
||||
import __builtin__
|
||||
self.context = __builtin__.__dict__
|
||||
|
||||
def parseExpression(self, exp):
|
||||
parsedvar = self.d.expandWithRefs(exp, None)
|
||||
parser = bb.codeparser.PythonParser("ParserTest", logger)
|
||||
parser.parse_python(parsedvar.value)
|
||||
|
||||
self.references = parsedvar.references | parser.references
|
||||
self.execs = parser.execs
|
||||
|
||||
@staticmethod
|
||||
def indent(value):
|
||||
"""Python Snippets have to be indented, python values don't have to
|
||||
be. These unit tests are testing snippets."""
|
||||
return " " + value
|
||||
|
||||
def test_getvar_reference(self):
|
||||
self.parseExpression("bb.data.getVar('foo', d, True)")
|
||||
self.assertReferences(set(["foo"]))
|
||||
self.assertExecs(set())
|
||||
|
||||
def test_getvar_computed_reference(self):
|
||||
self.parseExpression("bb.data.getVar('f' + 'o' + 'o', d, True)")
|
||||
self.assertReferences(set())
|
||||
self.assertExecs(set())
|
||||
|
||||
def test_getvar_exec_reference(self):
|
||||
self.parseExpression("eval('bb.data.getVar(\"foo\", d, True)')")
|
||||
self.assertReferences(set())
|
||||
self.assertExecs(set(["eval"]))
|
||||
|
||||
def test_var_reference(self):
|
||||
self.context["foo"] = lambda x: x
|
||||
self.setEmptyVars(["FOO"])
|
||||
self.parseExpression("foo('${FOO}')")
|
||||
self.assertReferences(set(["FOO"]))
|
||||
self.assertExecs(set(["foo"]))
|
||||
del self.context["foo"]
|
||||
|
||||
def test_var_exec(self):
|
||||
for etype in ("func", "task"):
|
||||
self.d.setVar("do_something", "echo 'hi mom! ${FOO}'")
|
||||
self.d.setVarFlag("do_something", etype, True)
|
||||
self.parseExpression("bb.build.exec_func('do_something', d)")
|
||||
self.assertReferences(set(["do_something"]))
|
||||
|
||||
def test_function_reference(self):
|
||||
self.context["testfunc"] = lambda msg: bb.msg.note(1, None, msg)
|
||||
self.d.setVar("FOO", "Hello, World!")
|
||||
self.parseExpression("testfunc('${FOO}')")
|
||||
self.assertReferences(set(["FOO"]))
|
||||
self.assertExecs(set(["testfunc"]))
|
||||
del self.context["testfunc"]
|
||||
|
||||
def test_qualified_function_reference(self):
|
||||
self.parseExpression("time.time()")
|
||||
self.assertExecs(set(["time.time"]))
|
||||
|
||||
def test_qualified_function_reference_2(self):
|
||||
self.parseExpression("os.path.dirname('/foo/bar')")
|
||||
self.assertExecs(set(["os.path.dirname"]))
|
||||
|
||||
def test_qualified_function_reference_nested(self):
|
||||
self.parseExpression("time.strftime('%Y%m%d',time.gmtime())")
|
||||
self.assertExecs(set(["time.strftime", "time.gmtime"]))
|
||||
|
||||
def test_function_reference_chained(self):
|
||||
self.context["testget"] = lambda: "\tstrip me "
|
||||
self.parseExpression("testget().strip()")
|
||||
self.assertExecs(set(["testget"]))
|
||||
del self.context["testget"]
|
||||
|
||||
|
||||
class DependencyReferenceTest(ReferenceTest):
|
||||
|
||||
pydata = """
|
||||
bb.data.getVar('somevar', d, True)
|
||||
def test(d):
|
||||
foo = 'bar %s' % 'foo'
|
||||
def test2(d):
|
||||
d.getVar(foo, True)
|
||||
d.getVar('bar', False)
|
||||
test2(d)
|
||||
|
||||
def a():
|
||||
\"\"\"some
|
||||
stuff
|
||||
\"\"\"
|
||||
return "heh"
|
||||
|
||||
test(d)
|
||||
|
||||
bb.data.expand(bb.data.getVar("something", False, d), d)
|
||||
bb.data.expand("${inexpand} somethingelse", d)
|
||||
bb.data.getVar(a(), d, False)
|
||||
"""
|
||||
|
||||
def test_python(self):
|
||||
self.d.setVar("FOO", self.pydata)
|
||||
self.setEmptyVars(["inexpand", "a", "test2", "test"])
|
||||
self.d.setVarFlags("FOO", {"func": True, "python": True})
|
||||
|
||||
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
|
||||
|
||||
self.assertEquals(deps, set(["somevar", "bar", "something", "inexpand", "test", "test2", "a"]))
|
||||
|
||||
|
||||
shelldata = """
|
||||
foo () {
|
||||
bar
|
||||
}
|
||||
{
|
||||
echo baz
|
||||
$(heh)
|
||||
eval `moo`
|
||||
}
|
||||
a=b
|
||||
c=d
|
||||
(
|
||||
true && false
|
||||
test -f foo
|
||||
testval=something
|
||||
$testval
|
||||
) || aiee
|
||||
! inverted
|
||||
echo ${somevar}
|
||||
|
||||
case foo in
|
||||
bar)
|
||||
echo bar
|
||||
;;
|
||||
baz)
|
||||
echo baz
|
||||
;;
|
||||
foo*)
|
||||
echo foo
|
||||
;;
|
||||
esac
|
||||
"""
|
||||
|
||||
def test_shell(self):
|
||||
execs = ["bar", "echo", "heh", "moo", "true", "aiee"]
|
||||
self.d.setVar("somevar", "heh")
|
||||
self.d.setVar("inverted", "echo inverted...")
|
||||
self.d.setVarFlag("inverted", "func", True)
|
||||
self.d.setVar("FOO", self.shelldata)
|
||||
self.d.setVarFlags("FOO", {"func": True})
|
||||
self.setEmptyVars(execs)
|
||||
|
||||
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
|
||||
|
||||
self.assertEquals(deps, set(["somevar", "inverted"] + execs))
|
||||
|
||||
|
||||
def test_vardeps(self):
|
||||
self.d.setVar("oe_libinstall", "echo test")
|
||||
self.d.setVar("FOO", "foo=oe_libinstall; eval $foo")
|
||||
self.d.setVarFlag("FOO", "vardeps", "oe_libinstall")
|
||||
|
||||
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
|
||||
|
||||
self.assertEquals(deps, set(["oe_libinstall"]))
|
||||
|
||||
def test_vardeps_expand(self):
|
||||
self.d.setVar("oe_libinstall", "echo test")
|
||||
self.d.setVar("FOO", "foo=oe_libinstall; eval $foo")
|
||||
self.d.setVarFlag("FOO", "vardeps", "${@'oe_libinstall'}")
|
||||
|
||||
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
|
||||
|
||||
self.assertEquals(deps, set(["oe_libinstall"]))
|
||||
|
||||
#Currently no wildcard support
|
||||
#def test_vardeps_wildcards(self):
|
||||
# self.d.setVar("oe_libinstall", "echo test")
|
||||
# self.d.setVar("FOO", "foo=oe_libinstall; eval $foo")
|
||||
# self.d.setVarFlag("FOO", "vardeps", "oe_*")
|
||||
# self.assertEquals(deps, set(["oe_libinstall"]))
|
||||
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
#
|
||||
# BitBake Tests for Copy-on-Write (cow.py)
|
||||
#
|
||||
# Copyright 2006 Holger Freyther <freyther@handhelds.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import os
|
||||
|
||||
class COWTestCase(unittest.TestCase):
|
||||
"""
|
||||
Test case for the COW module from mithro
|
||||
"""
|
||||
|
||||
def testGetSet(self):
|
||||
"""
|
||||
Test and set
|
||||
"""
|
||||
from bb.COW import COWDictBase
|
||||
a = COWDictBase.copy()
|
||||
|
||||
self.assertEquals(False, a.has_key('a'))
|
||||
|
||||
a['a'] = 'a'
|
||||
a['b'] = 'b'
|
||||
self.assertEquals(True, a.has_key('a'))
|
||||
self.assertEquals(True, a.has_key('b'))
|
||||
self.assertEquals('a', a['a'] )
|
||||
self.assertEquals('b', a['b'] )
|
||||
|
||||
def testCopyCopy(self):
|
||||
"""
|
||||
Test the copy of copies
|
||||
"""
|
||||
|
||||
from bb.COW import COWDictBase
|
||||
|
||||
# create two COW dict 'instances'
|
||||
b = COWDictBase.copy()
|
||||
c = COWDictBase.copy()
|
||||
|
||||
# assign some keys to one instance, some keys to another
|
||||
b['a'] = 10
|
||||
b['c'] = 20
|
||||
c['a'] = 30
|
||||
|
||||
# test separation of the two instances
|
||||
self.assertEquals(False, c.has_key('c'))
|
||||
self.assertEquals(30, c['a'])
|
||||
self.assertEquals(10, b['a'])
|
||||
|
||||
# test copy
|
||||
b_2 = b.copy()
|
||||
c_2 = c.copy()
|
||||
|
||||
self.assertEquals(False, c_2.has_key('c'))
|
||||
self.assertEquals(10, b_2['a'])
|
||||
|
||||
b_2['d'] = 40
|
||||
self.assertEquals(False, c_2.has_key('d'))
|
||||
self.assertEquals(True, b_2.has_key('d'))
|
||||
self.assertEquals(40, b_2['d'])
|
||||
self.assertEquals(False, b.has_key('d'))
|
||||
self.assertEquals(False, c.has_key('d'))
|
||||
|
||||
c_2['d'] = 30
|
||||
self.assertEquals(True, c_2.has_key('d'))
|
||||
self.assertEquals(True, b_2.has_key('d'))
|
||||
self.assertEquals(30, c_2['d'])
|
||||
self.assertEquals(40, b_2['d'])
|
||||
self.assertEquals(False, b.has_key('d'))
|
||||
self.assertEquals(False, c.has_key('d'))
|
||||
|
||||
# test copy of the copy
|
||||
c_3 = c_2.copy()
|
||||
b_3 = b_2.copy()
|
||||
b_3_2 = b_2.copy()
|
||||
|
||||
c_3['e'] = 4711
|
||||
self.assertEquals(4711, c_3['e'])
|
||||
self.assertEquals(False, c_2.has_key('e'))
|
||||
self.assertEquals(False, b_3.has_key('e'))
|
||||
self.assertEquals(False, b_3_2.has_key('e'))
|
||||
self.assertEquals(False, b_2.has_key('e'))
|
||||
|
||||
b_3['e'] = 'viel'
|
||||
self.assertEquals('viel', b_3['e'])
|
||||
self.assertEquals(4711, c_3['e'])
|
||||
self.assertEquals(False, c_2.has_key('e'))
|
||||
self.assertEquals(True, b_3.has_key('e'))
|
||||
self.assertEquals(False, b_3_2.has_key('e'))
|
||||
self.assertEquals(False, b_2.has_key('e'))
|
||||
|
||||
def testCow(self):
|
||||
from bb.COW import COWDictBase
|
||||
c = COWDictBase.copy()
|
||||
c['123'] = 1027
|
||||
c['other'] = 4711
|
||||
c['d'] = { 'abc' : 10, 'bcd' : 20 }
|
||||
|
||||
copy = c.copy()
|
||||
|
||||
self.assertEquals(1027, c['123'])
|
||||
self.assertEquals(4711, c['other'])
|
||||
self.assertEquals({'abc':10, 'bcd':20}, c['d'])
|
||||
self.assertEquals(1027, copy['123'])
|
||||
self.assertEquals(4711, copy['other'])
|
||||
self.assertEquals({'abc':10, 'bcd':20}, copy['d'])
|
||||
|
||||
# cow it now
|
||||
copy['123'] = 1028
|
||||
copy['other'] = 4712
|
||||
copy['d']['abc'] = 20
|
||||
|
||||
|
||||
self.assertEquals(1027, c['123'])
|
||||
self.assertEquals(4711, c['other'])
|
||||
self.assertEquals({'abc':10, 'bcd':20}, c['d'])
|
||||
self.assertEquals(1028, copy['123'])
|
||||
self.assertEquals(4712, copy['other'])
|
||||
self.assertEquals({'abc':20, 'bcd':20}, copy['d'])
|
||||
@@ -1,252 +0,0 @@
|
||||
#
|
||||
# BitBake Tests for the Data Store (data.py/data_smart.py)
|
||||
#
|
||||
# Copyright (C) 2010 Chris Larson
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import bb
|
||||
import bb.data
|
||||
|
||||
class DataExpansions(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.d["foo"] = "value of foo"
|
||||
self.d["bar"] = "value of bar"
|
||||
self.d["value of foo"] = "value of 'value of foo'"
|
||||
|
||||
def test_one_var(self):
|
||||
val = self.d.expand("${foo}")
|
||||
self.assertEqual(str(val), "value of foo")
|
||||
|
||||
def test_indirect_one_var(self):
|
||||
val = self.d.expand("${${foo}}")
|
||||
self.assertEqual(str(val), "value of 'value of foo'")
|
||||
|
||||
def test_indirect_and_another(self):
|
||||
val = self.d.expand("${${foo}} ${bar}")
|
||||
self.assertEqual(str(val), "value of 'value of foo' value of bar")
|
||||
|
||||
def test_python_snippet(self):
|
||||
val = self.d.expand("${@5*12}")
|
||||
self.assertEqual(str(val), "60")
|
||||
|
||||
def test_expand_in_python_snippet(self):
|
||||
val = self.d.expand("${@'boo ' + '${foo}'}")
|
||||
self.assertEqual(str(val), "boo value of foo")
|
||||
|
||||
def test_python_snippet_getvar(self):
|
||||
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
|
||||
self.assertEqual(str(val), "value of foo value of bar")
|
||||
|
||||
def test_python_snippet_syntax_error(self):
|
||||
self.d.setVar("FOO", "${@foo = 5}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_python_snippet_runtime_error(self):
|
||||
self.d.setVar("FOO", "${@int('test')}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_python_snippet_error_path(self):
|
||||
self.d.setVar("FOO", "foo value ${BAR}")
|
||||
self.d.setVar("BAR", "bar value ${@int('test')}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_value_containing_value(self):
|
||||
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
|
||||
self.assertEqual(str(val), "value of foo value of bar")
|
||||
|
||||
def test_reference_undefined_var(self):
|
||||
val = self.d.expand("${undefinedvar} meh")
|
||||
self.assertEqual(str(val), "${undefinedvar} meh")
|
||||
|
||||
def test_double_reference(self):
|
||||
self.d.setVar("BAR", "bar value")
|
||||
self.d.setVar("FOO", "${BAR} foo ${BAR}")
|
||||
val = self.d.getVar("FOO", True)
|
||||
self.assertEqual(str(val), "bar value foo bar value")
|
||||
|
||||
def test_direct_recursion(self):
|
||||
self.d.setVar("FOO", "${FOO}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_indirect_recursion(self):
|
||||
self.d.setVar("FOO", "${BAR}")
|
||||
self.d.setVar("BAR", "${BAZ}")
|
||||
self.d.setVar("BAZ", "${FOO}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_recursion_exception(self):
|
||||
self.d.setVar("FOO", "${BAR}")
|
||||
self.d.setVar("BAR", "${${@'FOO'}}")
|
||||
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
|
||||
|
||||
def test_incomplete_varexp_single_quotes(self):
|
||||
self.d.setVar("FOO", "sed -i -e 's:IP{:I${:g' $pc")
|
||||
val = self.d.getVar("FOO", True)
|
||||
self.assertEqual(str(val), "sed -i -e 's:IP{:I${:g' $pc")
|
||||
|
||||
def test_nonstring(self):
|
||||
self.d.setVar("TEST", 5)
|
||||
val = self.d.getVar("TEST", True)
|
||||
self.assertEqual(str(val), "5")
|
||||
|
||||
def test_rename(self):
|
||||
self.d.renameVar("foo", "newfoo")
|
||||
self.assertEqual(self.d.getVar("newfoo"), "value of foo")
|
||||
self.assertEqual(self.d.getVar("foo"), None)
|
||||
|
||||
def test_deletion(self):
|
||||
self.d.delVar("foo")
|
||||
self.assertEqual(self.d.getVar("foo"), None)
|
||||
|
||||
def test_keys(self):
|
||||
keys = self.d.keys()
|
||||
self.assertEqual(keys, ['value of foo', 'foo', 'bar'])
|
||||
|
||||
class TestNestedExpansions(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.d["foo"] = "foo"
|
||||
self.d["bar"] = "bar"
|
||||
self.d["value of foobar"] = "187"
|
||||
|
||||
def test_refs(self):
|
||||
val = self.d.expand("${value of ${foo}${bar}}")
|
||||
self.assertEqual(str(val), "187")
|
||||
|
||||
#def test_python_refs(self):
|
||||
# val = self.d.expand("${@${@3}**2 + ${@4}**2}")
|
||||
# self.assertEqual(str(val), "25")
|
||||
|
||||
def test_ref_in_python_ref(self):
|
||||
val = self.d.expand("${@'${foo}' + 'bar'}")
|
||||
self.assertEqual(str(val), "foobar")
|
||||
|
||||
def test_python_ref_in_ref(self):
|
||||
val = self.d.expand("${${@'f'+'o'+'o'}}")
|
||||
self.assertEqual(str(val), "foo")
|
||||
|
||||
def test_deep_nesting(self):
|
||||
depth = 100
|
||||
val = self.d.expand("${" * depth + "foo" + "}" * depth)
|
||||
self.assertEqual(str(val), "foo")
|
||||
|
||||
#def test_deep_python_nesting(self):
|
||||
# depth = 50
|
||||
# val = self.d.expand("${@" * depth + "1" + "+1}" * depth)
|
||||
# self.assertEqual(str(val), str(depth + 1))
|
||||
|
||||
def test_mixed(self):
|
||||
val = self.d.expand("${value of ${@('${foo}'+'bar')[0:3]}${${@'BAR'.lower()}}}")
|
||||
self.assertEqual(str(val), "187")
|
||||
|
||||
def test_runtime(self):
|
||||
val = self.d.expand("${${@'value of' + ' f'+'o'+'o'+'b'+'a'+'r'}}")
|
||||
self.assertEqual(str(val), "187")
|
||||
|
||||
class TestMemoize(unittest.TestCase):
|
||||
def test_memoized(self):
|
||||
d = bb.data.init()
|
||||
d.setVar("FOO", "bar")
|
||||
self.assertTrue(d.getVar("FOO") is d.getVar("FOO"))
|
||||
|
||||
def test_not_memoized(self):
|
||||
d1 = bb.data.init()
|
||||
d2 = bb.data.init()
|
||||
d1.setVar("FOO", "bar")
|
||||
d2.setVar("FOO", "bar2")
|
||||
self.assertTrue(d1.getVar("FOO") is not d2.getVar("FOO"))
|
||||
|
||||
def test_changed_after_memoized(self):
|
||||
d = bb.data.init()
|
||||
d.setVar("foo", "value of foo")
|
||||
self.assertEqual(str(d.getVar("foo")), "value of foo")
|
||||
d.setVar("foo", "second value of foo")
|
||||
self.assertEqual(str(d.getVar("foo")), "second value of foo")
|
||||
|
||||
def test_same_value(self):
|
||||
d = bb.data.init()
|
||||
d.setVar("foo", "value of")
|
||||
d.setVar("bar", "value of")
|
||||
self.assertEqual(d.getVar("foo"),
|
||||
d.getVar("bar"))
|
||||
|
||||
class TestConcat(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.d.setVar("FOO", "foo")
|
||||
self.d.setVar("VAL", "val")
|
||||
self.d.setVar("BAR", "bar")
|
||||
|
||||
def test_prepend(self):
|
||||
self.d.setVar("TEST", "${VAL}")
|
||||
self.d.prependVar("TEST", "${FOO}:")
|
||||
self.assertEqual(self.d.getVar("TEST", True), "foo:val")
|
||||
|
||||
def test_append(self):
|
||||
self.d.setVar("TEST", "${VAL}")
|
||||
self.d.appendVar("TEST", ":${BAR}")
|
||||
self.assertEqual(self.d.getVar("TEST", True), "val:bar")
|
||||
|
||||
def test_multiple_append(self):
|
||||
self.d.setVar("TEST", "${VAL}")
|
||||
self.d.prependVar("TEST", "${FOO}:")
|
||||
self.d.appendVar("TEST", ":val2")
|
||||
self.d.appendVar("TEST", ":${BAR}")
|
||||
self.assertEqual(self.d.getVar("TEST", True), "foo:val:val2:bar")
|
||||
|
||||
class TestOverrides(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.d.setVar("OVERRIDES", "foo:bar:local")
|
||||
self.d.setVar("TEST", "testvalue")
|
||||
|
||||
def test_no_override(self):
|
||||
bb.data.update_data(self.d)
|
||||
self.assertEqual(self.d.getVar("TEST", True), "testvalue")
|
||||
|
||||
def test_one_override(self):
|
||||
self.d.setVar("TEST_bar", "testvalue2")
|
||||
bb.data.update_data(self.d)
|
||||
self.assertEqual(self.d.getVar("TEST", True), "testvalue2")
|
||||
|
||||
def test_multiple_override(self):
|
||||
self.d.setVar("TEST_bar", "testvalue2")
|
||||
self.d.setVar("TEST_local", "testvalue3")
|
||||
self.d.setVar("TEST_foo", "testvalue4")
|
||||
bb.data.update_data(self.d)
|
||||
self.assertEqual(self.d.getVar("TEST", True), "testvalue3")
|
||||
|
||||
|
||||
class TestFlags(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.d.setVar("foo", "value of foo")
|
||||
self.d.setVarFlag("foo", "flag1", "value of flag1")
|
||||
self.d.setVarFlag("foo", "flag2", "value of flag2")
|
||||
|
||||
def test_setflag(self):
|
||||
self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
|
||||
self.assertEqual(self.d.getVarFlag("foo", "flag2"), "value of flag2")
|
||||
|
||||
def test_delflag(self):
|
||||
self.d.delVarFlag("foo", "flag2")
|
||||
self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
|
||||
self.assertEqual(self.d.getVarFlag("foo", "flag2"), None)
|
||||
|
||||
|
||||
@@ -1,191 +0,0 @@
|
||||
#
|
||||
# BitBake Tests for the Fetcher (fetch2/)
|
||||
#
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import tempfile
|
||||
import subprocess
|
||||
import os
|
||||
import bb
|
||||
|
||||
|
||||
class FetcherTest(unittest.TestCase):
|
||||
|
||||
replaceuris = {
|
||||
("git://git.invalid.infradead.org/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/.*", "http://somewhere.org/somedir/")
|
||||
: "http://somewhere.org/somedir/git2_git.invalid.infradead.org.mtd-utils.git.tar.gz",
|
||||
("git://git.invalid.infradead.org/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/([^/]+/)*([^/]*)", "git://somewhere.org/somedir/\\2;protocol=http")
|
||||
: "git://somewhere.org/somedir/mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
("git://git.invalid.infradead.org/foo/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/([^/]+/)*([^/]*)", "git://somewhere.org/somedir/\\2;protocol=http")
|
||||
: "git://somewhere.org/somedir/mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
("git://git.invalid.infradead.org/foo/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/([^/]+/)*([^/]*)", "git://somewhere.org/\\2;protocol=http")
|
||||
: "git://somewhere.org/mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
("git://someserver.org/bitbake;tag=1234567890123456789012345678901234567890", "git://someserver.org/bitbake", "git://git.openembedded.org/bitbake")
|
||||
: "git://git.openembedded.org/bitbake;tag=1234567890123456789012345678901234567890",
|
||||
("file://sstate-xyz.tgz", "file://.*", "file:///somewhere/1234/sstate-cache")
|
||||
: "file:///somewhere/1234/sstate-cache/sstate-xyz.tgz",
|
||||
("file://sstate-xyz.tgz", "file://.*", "file:///somewhere/1234/sstate-cache/")
|
||||
: "file:///somewhere/1234/sstate-cache/sstate-xyz.tgz",
|
||||
("http://somewhere.org/somedir1/somedir2/somefile_1.2.3.tar.gz", "http://.*/.*", "http://somewhere2.org/somedir3")
|
||||
: "http://somewhere2.org/somedir3/somefile_1.2.3.tar.gz",
|
||||
("http://somewhere.org/somedir1/somefile_1.2.3.tar.gz", "http://somewhere.org/somedir1/somefile_1.2.3.tar.gz", "http://somewhere2.org/somedir3/somefile_1.2.3.tar.gz")
|
||||
: "http://somewhere2.org/somedir3/somefile_1.2.3.tar.gz",
|
||||
("http://www.apache.org/dist/subversion/subversion-1.7.1.tar.bz2", "http://www.apache.org/dist", "http://archive.apache.org/dist")
|
||||
: "http://archive.apache.org/dist/subversion/subversion-1.7.1.tar.bz2",
|
||||
("http://www.apache.org/dist/subversion/subversion-1.7.1.tar.bz2", "http://.*/.*", "file:///somepath/downloads/")
|
||||
: "file:///somepath/downloads/subversion-1.7.1.tar.bz2",
|
||||
("git://git.invalid.infradead.org/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/.*", "git://somewhere.org/somedir/BASENAME;protocol=http")
|
||||
: "git://somewhere.org/somedir/mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
("git://git.invalid.infradead.org/foo/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/.*", "git://somewhere.org/somedir/BASENAME;protocol=http")
|
||||
: "git://somewhere.org/somedir/mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
("git://git.invalid.infradead.org/foo/mtd-utils.git;tag=1234567890123456789012345678901234567890", "git://.*/.*", "git://somewhere.org/somedir/MIRRORNAME;protocol=http")
|
||||
: "git://somewhere.org/somedir/git.invalid.infradead.org.foo.mtd-utils.git;tag=1234567890123456789012345678901234567890;protocol=http",
|
||||
|
||||
#Renaming files doesn't work
|
||||
#("http://somewhere.org/somedir1/somefile_1.2.3.tar.gz", "http://somewhere.org/somedir1/somefile_1.2.3.tar.gz", "http://somewhere2.org/somedir3/somefile_2.3.4.tar.gz") : "http://somewhere2.org/somedir3/somefile_2.3.4.tar.gz"
|
||||
#("file://sstate-xyz.tgz", "file://.*/.*", "file:///somewhere/1234/sstate-cache") : "file:///somewhere/1234/sstate-cache/sstate-xyz.tgz",
|
||||
}
|
||||
|
||||
mirrorvar = "http://.*/.* file:///somepath/downloads/ \n" \
|
||||
"git://someserver.org/bitbake git://git.openembedded.org/bitbake \n" \
|
||||
"https://.*/.* file:///someotherpath/downloads/ \n" \
|
||||
"http://.*/.* file:///someotherpath/downloads/ \n"
|
||||
|
||||
def setUp(self):
|
||||
self.d = bb.data.init()
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
self.dldir = os.path.join(self.tempdir, "download")
|
||||
os.mkdir(self.dldir)
|
||||
self.d.setVar("DL_DIR", self.dldir)
|
||||
self.unpackdir = os.path.join(self.tempdir, "unpacked")
|
||||
os.mkdir(self.unpackdir)
|
||||
persistdir = os.path.join(self.tempdir, "persistdata")
|
||||
self.d.setVar("PERSISTENT_DIR", persistdir)
|
||||
|
||||
def tearDown(self):
|
||||
bb.utils.prunedir(self.tempdir)
|
||||
|
||||
def test_fetch(self):
|
||||
fetcher = bb.fetch.Fetch(["http://downloads.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz", "http://downloads.yoctoproject.org/releases/bitbake/bitbake-1.1.tar.gz"], self.d)
|
||||
fetcher.download()
|
||||
self.assertEqual(os.path.getsize(self.dldir + "/bitbake-1.0.tar.gz"), 57749)
|
||||
self.assertEqual(os.path.getsize(self.dldir + "/bitbake-1.1.tar.gz"), 57892)
|
||||
self.d.setVar("BB_NO_NETWORK", "1")
|
||||
fetcher = bb.fetch.Fetch(["http://downloads.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz", "http://downloads.yoctoproject.org/releases/bitbake/bitbake-1.1.tar.gz"], self.d)
|
||||
fetcher.download()
|
||||
fetcher.unpack(self.unpackdir)
|
||||
self.assertEqual(len(os.listdir(self.unpackdir + "/bitbake-1.0/")), 9)
|
||||
self.assertEqual(len(os.listdir(self.unpackdir + "/bitbake-1.1/")), 9)
|
||||
|
||||
def test_fetch_mirror(self):
|
||||
self.d.setVar("MIRRORS", "http://.*/.* http://downloads.yoctoproject.org/releases/bitbake")
|
||||
fetcher = bb.fetch.Fetch(["http://invalid.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz"], self.d)
|
||||
fetcher.download()
|
||||
self.assertEqual(os.path.getsize(self.dldir + "/bitbake-1.0.tar.gz"), 57749)
|
||||
|
||||
def test_fetch_premirror(self):
|
||||
self.d.setVar("PREMIRRORS", "http://.*/.* http://downloads.yoctoproject.org/releases/bitbake")
|
||||
fetcher = bb.fetch.Fetch(["http://invalid.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz"], self.d)
|
||||
fetcher.download()
|
||||
self.assertEqual(os.path.getsize(self.dldir + "/bitbake-1.0.tar.gz"), 57749)
|
||||
|
||||
def gitfetcher(self, url1, url2):
|
||||
def checkrevision(self, fetcher):
|
||||
fetcher.unpack(self.unpackdir)
|
||||
revision = subprocess.check_output("git rev-parse HEAD", shell=True, cwd=self.unpackdir + "/git").strip()
|
||||
self.assertEqual(revision, "270a05b0b4ba0959fe0624d2a4885d7b70426da5")
|
||||
|
||||
self.d.setVar("BB_GENERATE_MIRROR_TARBALLS", "1")
|
||||
self.d.setVar("SRCREV", "270a05b0b4ba0959fe0624d2a4885d7b70426da5")
|
||||
fetcher = bb.fetch.Fetch([url1], self.d)
|
||||
fetcher.download()
|
||||
checkrevision(self, fetcher)
|
||||
# Wipe out the dldir clone and the unpacked source, turn off the network and check mirror tarball works
|
||||
bb.utils.prunedir(self.dldir + "/git2/")
|
||||
bb.utils.prunedir(self.unpackdir)
|
||||
self.d.setVar("BB_NO_NETWORK", "1")
|
||||
fetcher = bb.fetch.Fetch([url2], self.d)
|
||||
fetcher.download()
|
||||
checkrevision(self, fetcher)
|
||||
|
||||
def test_gitfetch(self):
|
||||
url1 = url2 = "git://git.openembedded.org/bitbake"
|
||||
self.gitfetcher(url1, url2)
|
||||
|
||||
def test_gitfetch_premirror(self):
|
||||
url1 = "git://git.openembedded.org/bitbake"
|
||||
url2 = "git://someserver.org/bitbake"
|
||||
self.d.setVar("PREMIRRORS", "git://someserver.org/bitbake git://git.openembedded.org/bitbake \n")
|
||||
self.gitfetcher(url1, url2)
|
||||
|
||||
def test_gitfetch_premirror2(self):
|
||||
url1 = url2 = "git://someserver.org/bitbake"
|
||||
self.d.setVar("PREMIRRORS", "git://someserver.org/bitbake git://git.openembedded.org/bitbake \n")
|
||||
self.gitfetcher(url1, url2)
|
||||
|
||||
def test_gitfetch_premirror3(self):
|
||||
realurl = "git://git.openembedded.org/bitbake"
|
||||
dummyurl = "git://someserver.org/bitbake"
|
||||
self.sourcedir = self.unpackdir.replace("unpacked", "sourcemirror.git")
|
||||
os.chdir(self.tempdir)
|
||||
subprocess.check_output("git clone %s %s 2> /dev/null" % (realurl, self.sourcedir), shell=True)
|
||||
self.d.setVar("PREMIRRORS", "%s git://%s;protocol=file \n" % (dummyurl, self.sourcedir))
|
||||
self.gitfetcher(dummyurl, dummyurl)
|
||||
|
||||
def test_urireplace(self):
|
||||
for k, v in self.replaceuris.items():
|
||||
ud = bb.fetch.FetchData(k[0], self.d)
|
||||
ud.setup_localpath(self.d)
|
||||
mirrors = bb.fetch2.mirror_from_string("%s %s" % (k[1], k[2]))
|
||||
newuris, uds = bb.fetch2.build_mirroruris(ud, mirrors, self.d)
|
||||
self.assertEqual([v], newuris)
|
||||
|
||||
def test_urilist1(self):
|
||||
fetcher = bb.fetch.FetchData("http://downloads.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz", self.d)
|
||||
mirrors = bb.fetch2.mirror_from_string(self.mirrorvar)
|
||||
uris, uds = bb.fetch2.build_mirroruris(fetcher, mirrors, self.d)
|
||||
self.assertEqual(uris, ['file:///somepath/downloads/bitbake-1.0.tar.gz', 'file:///someotherpath/downloads/bitbake-1.0.tar.gz'])
|
||||
|
||||
def test_urilist2(self):
|
||||
# Catch https:// -> files:// bug
|
||||
fetcher = bb.fetch.FetchData("https://downloads.yoctoproject.org/releases/bitbake/bitbake-1.0.tar.gz", self.d)
|
||||
mirrors = bb.fetch2.mirror_from_string(self.mirrorvar)
|
||||
uris, uds = bb.fetch2.build_mirroruris(fetcher, mirrors, self.d)
|
||||
self.assertEqual(uris, ['file:///someotherpath/downloads/bitbake-1.0.tar.gz'])
|
||||
|
||||
|
||||
class URLHandle(unittest.TestCase):
|
||||
|
||||
datatable = {
|
||||
"http://www.google.com/index.html" : ('http', 'www.google.com', '/index.html', '', '', {}),
|
||||
"cvs://anoncvs@cvs.handhelds.org/cvs;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', '', {'module': 'familiar/dist/ipkg'}),
|
||||
"cvs://anoncvs:anonymous@cvs.handhelds.org/cvs;tag=V0-99-81;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', 'anonymous', {'tag': 'V0-99-81', 'module': 'familiar/dist/ipkg'})
|
||||
}
|
||||
|
||||
def test_decodeurl(self):
|
||||
for k, v in self.datatable.items():
|
||||
result = bb.fetch.decodeurl(k)
|
||||
self.assertEqual(result, v)
|
||||
|
||||
def test_encodeurl(self):
|
||||
for k, v in self.datatable.items():
|
||||
result = bb.fetch.encodeurl(v)
|
||||
self.assertEqual(result, k)
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#
|
||||
# BitBake Tests for utils.py
|
||||
#
|
||||
# Copyright (C) 2012 Richard Purdie
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License version 2 as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import unittest
|
||||
import bb
|
||||
|
||||
class VerCmpString(unittest.TestCase):
|
||||
|
||||
def test_vercmpstring(self):
|
||||
result = bb.utils.vercmp_string('1', '2')
|
||||
self.assertTrue(result < 0)
|
||||
result = bb.utils.vercmp_string('2', '1')
|
||||
self.assertTrue(result > 0)
|
||||
result = bb.utils.vercmp_string('1', '1.0')
|
||||
self.assertTrue(result < 0)
|
||||
result = bb.utils.vercmp_string('1', '1.1')
|
||||
self.assertTrue(result < 0)
|
||||
result = bb.utils.vercmp_string('1.1', '1_p2')
|
||||
self.assertTrue(result < 0)
|
||||
|
||||
@@ -23,13 +23,11 @@
|
||||
import gtk
|
||||
import pango
|
||||
import gobject
|
||||
import bb.process
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.hobwidget import hic, HobNotebook, HobAltButton, HobWarpCellRendererText, HobButton, HobInfoButton
|
||||
from bb.ui.crumbs.hobwidget import hic, HobNotebook, HobAltButton, HobWarpCellRendererText
|
||||
from bb.ui.crumbs.runningbuild import RunningBuildTreeView
|
||||
from bb.ui.crumbs.runningbuild import BuildFailureTreeView
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
|
||||
class BuildConfigurationTreeView(gtk.TreeView):
|
||||
def __init__ (self):
|
||||
@@ -98,10 +96,11 @@ class BuildConfigurationTreeView(gtk.TreeView):
|
||||
for path in src_config_info.layers:
|
||||
import os, os.path
|
||||
if os.path.exists(path):
|
||||
branch = bb.process.run('cd %s; git branch | grep "^* " | tr -d "* "' % path)[0]
|
||||
if branch:
|
||||
branch = branch.strip('\n')
|
||||
f = os.popen('cd %s; git branch 2>&1 | grep "^* " | tr -d "* "' % path)
|
||||
if f:
|
||||
branch = f.readline().lstrip('\n').rstrip('\n')
|
||||
vars.append(self.set_vars("Branch:", branch))
|
||||
f.close()
|
||||
break
|
||||
|
||||
self.set_config_model(vars)
|
||||
@@ -145,7 +144,7 @@ class BuildDetailsPage (HobPage):
|
||||
self.scrolled_view_config = gtk.ScrolledWindow ()
|
||||
self.scrolled_view_config.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
self.scrolled_view_config.add(self.config_tv)
|
||||
self.notebook.append_page(self.scrolled_view_config, "Build configuration")
|
||||
self.notebook.append_page(self.scrolled_view_config, gtk.Label("Build configuration"))
|
||||
|
||||
self.failure_tv = BuildFailureTreeView()
|
||||
self.failure_model = self.builder.handler.build.model.failure_model()
|
||||
@@ -153,14 +152,14 @@ class BuildDetailsPage (HobPage):
|
||||
self.scrolled_view_failure = gtk.ScrolledWindow ()
|
||||
self.scrolled_view_failure.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
self.scrolled_view_failure.add(self.failure_tv)
|
||||
self.notebook.append_page(self.scrolled_view_failure, "Issues")
|
||||
self.notebook.append_page(self.scrolled_view_failure, gtk.Label("Issues"))
|
||||
|
||||
self.build_tv = RunningBuildTreeView(readonly=True, hob=True)
|
||||
self.build_tv.set_model(self.builder.handler.build.model)
|
||||
self.scrolled_view_build = gtk.ScrolledWindow ()
|
||||
self.scrolled_view_build.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
self.scrolled_view_build.add(self.build_tv)
|
||||
self.notebook.append_page(self.scrolled_view_build, "Log")
|
||||
self.notebook.append_page(self.scrolled_view_build, gtk.Label("Log"))
|
||||
|
||||
self.builder.handler.build.model.connect_after("row-changed", self.scroll_to_present_row, self.scrolled_view_build.get_vadjustment(), self.build_tv)
|
||||
|
||||
@@ -199,70 +198,6 @@ class BuildDetailsPage (HobPage):
|
||||
for child in children:
|
||||
self.remove(child)
|
||||
|
||||
def add_build_fail_top_bar(self, actions, log_file=None):
|
||||
primary_action = "Edit %s" % actions
|
||||
|
||||
self.notebook.set_page("Issues")
|
||||
|
||||
color = HobColors.ERROR
|
||||
build_fail_top = gtk.EventBox()
|
||||
build_fail_top.set_size_request(-1, 200)
|
||||
build_fail_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
|
||||
|
||||
build_fail_tab = gtk.Table(14, 46, True)
|
||||
build_fail_top.add(build_fail_tab)
|
||||
|
||||
icon = gtk.Image()
|
||||
icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ERROR_FILE)
|
||||
icon.set_from_pixbuf(icon_pix_buffer)
|
||||
build_fail_tab.attach(icon, 1, 4, 0, 6)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_markup("<span size='x-large'><b>%s</b></span>" % self.title)
|
||||
build_fail_tab.attach(label, 4, 26, 0, 6)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_markup("<span size='medium'>Check the \"Issues\" information for more details</span>")
|
||||
build_fail_tab.attach(label, 4, 40, 4, 9)
|
||||
|
||||
# create button 'Edit packages'
|
||||
action_button = HobButton(primary_action)
|
||||
action_button.set_size_request(-1, 40)
|
||||
action_button.connect('clicked', self.failure_primary_action_button_clicked_cb, primary_action)
|
||||
build_fail_tab.attach(action_button, 4, 13, 9, 12)
|
||||
|
||||
if log_file:
|
||||
open_log_button = HobAltButton("Open log")
|
||||
open_log_button.set_relief(gtk.RELIEF_HALF)
|
||||
open_log_button.connect('clicked', self.failure_open_log_button_clicked_cb, log_file)
|
||||
build_fail_tab.attach(open_log_button, 14, 23, 9, 12)
|
||||
|
||||
attach_pos = (24 if log_file else 14)
|
||||
file_bug_button = HobAltButton('File a bug')
|
||||
file_bug_button.set_relief(gtk.RELIEF_HALF)
|
||||
file_bug_button.connect('clicked', self.failure_activate_file_bug_link_cb)
|
||||
build_fail_tab.attach(file_bug_button, attach_pos, attach_pos + 9, 9, 12)
|
||||
|
||||
return build_fail_top
|
||||
|
||||
def show_fail_page(self, title, action_names):
|
||||
self._remove_all_widget()
|
||||
self.title = "Hob cannot build your %s" % title
|
||||
|
||||
self.build_fail_bar = self.add_build_fail_top_bar(action_names, self.builder.current_logfile)
|
||||
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
self.box_group_area.pack_start(self.build_fail_bar, expand=False, fill=False)
|
||||
self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
|
||||
|
||||
self.vbox.pack_start(self.notebook, expand=True, fill=True)
|
||||
|
||||
self.box_group_area.pack_end(self.button_box, expand=False, fill=False)
|
||||
self.show_all()
|
||||
self.back_button.hide()
|
||||
|
||||
def show_page(self, step):
|
||||
self._remove_all_widget()
|
||||
if step == self.builder.PACKAGE_GENERATING or step == self.builder.FAST_IMAGE_GENERATING:
|
||||
@@ -316,18 +251,3 @@ class BuildDetailsPage (HobPage):
|
||||
|
||||
def show_configurations(self, configurations, params):
|
||||
self.config_tv.show(configurations, params)
|
||||
|
||||
def failure_primary_action_button_clicked_cb(self, button, action):
|
||||
if "Edit recipes" in action:
|
||||
self.builder.show_recipes()
|
||||
elif "Edit packages" in action:
|
||||
self.builder.show_packages()
|
||||
elif "Edit image configuration" in action:
|
||||
self.builder.show_configuration()
|
||||
|
||||
def failure_open_log_button_clicked_cb(self, button, log_file):
|
||||
if log_file:
|
||||
os.system("xdg-open /%s" % log_file)
|
||||
|
||||
def failure_activate_file_bug_link_cb(self, button):
|
||||
button.child.emit('activate-link', "http://bugzilla.yoctoproject.org")
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import glib
|
||||
import gtk
|
||||
import copy
|
||||
import os
|
||||
import subprocess
|
||||
import shlex
|
||||
import re
|
||||
import logging
|
||||
from bb.ui.crumbs.template import TemplateMgr
|
||||
from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
|
||||
from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
|
||||
@@ -41,49 +40,9 @@ from bb.ui.crumbs.hig import CrumbsMessageDialog, ImageSelectionDialog, \
|
||||
from bb.ui.crumbs.persistenttooltip import PersistentTooltip
|
||||
import bb.ui.crumbs.utils
|
||||
|
||||
hobVer = 20120530
|
||||
|
||||
class Configuration:
|
||||
'''Represents the data structure of configuration.'''
|
||||
|
||||
@classmethod
|
||||
def parse_proxy_string(cls, proxy):
|
||||
pattern = "^\s*((http|https|ftp|git|cvs)://)?((\S+):(\S+)@)?(\S+):(\d+)/?"
|
||||
match = re.search(pattern, proxy)
|
||||
if match:
|
||||
return match.group(2), match.group(4), match.group(5), match.group(6), match.group(7)
|
||||
else:
|
||||
return None, None, None, "", ""
|
||||
|
||||
@classmethod
|
||||
def make_host_string(cls, prot, user, passwd, host, default_prot=""):
|
||||
if host == None or host == "":
|
||||
return ""
|
||||
|
||||
passwd = passwd or ""
|
||||
|
||||
if user != None and user != "":
|
||||
if prot == None or prot == "":
|
||||
prot = default_prot
|
||||
return prot + "://" + user + ":" + passwd + "@" + host
|
||||
else:
|
||||
if prot == None or prot == "":
|
||||
return host
|
||||
else:
|
||||
return prot + "://" + host
|
||||
|
||||
@classmethod
|
||||
def make_port_string(cls, port):
|
||||
port = port or ""
|
||||
return port
|
||||
|
||||
@classmethod
|
||||
def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
|
||||
if host == None or host == "" or port == None or port == "":
|
||||
return ""
|
||||
|
||||
return Configuration.make_host_string(prot, user, passwd, host, default_prot) + ":" + Configuration.make_port_string(port)
|
||||
|
||||
def __init__(self):
|
||||
self.curr_mach = ""
|
||||
# settings
|
||||
@@ -109,43 +68,16 @@ class Configuration:
|
||||
self.default_task = "build"
|
||||
|
||||
# proxy settings
|
||||
self.all_proxy = self.http_proxy = self.ftp_proxy = self.https_proxy = ""
|
||||
self.git_proxy_host = self.git_proxy_port = ""
|
||||
self.cvs_proxy_host = self.cvs_proxy_port = ""
|
||||
self.enable_proxy = None
|
||||
self.same_proxy = False
|
||||
self.proxies = {
|
||||
"http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
|
||||
"https" : [None, None, None, "", ""],
|
||||
"ftp" : [None, None, None, "", ""],
|
||||
"git" : [None, None, None, "", ""],
|
||||
"cvs" : [None, None, None, "", ""],
|
||||
}
|
||||
|
||||
def clear_selection(self):
|
||||
self.selected_image = None
|
||||
self.selected_recipes = []
|
||||
self.selected_packages = []
|
||||
|
||||
def split_proxy(self, protocol, proxy):
|
||||
entry = []
|
||||
prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
|
||||
entry.append(prot)
|
||||
entry.append(user)
|
||||
entry.append(passwd)
|
||||
entry.append(host)
|
||||
entry.append(port)
|
||||
self.proxies[protocol] = entry
|
||||
|
||||
def combine_proxy(self, protocol):
|
||||
entry = self.proxies[protocol]
|
||||
return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
|
||||
|
||||
def combine_host_only(self, protocol):
|
||||
entry = self.proxies[protocol]
|
||||
return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
|
||||
|
||||
def combine_port_only(self, protocol):
|
||||
entry = self.proxies[protocol]
|
||||
return Configuration.make_port_string(entry[4])
|
||||
|
||||
def update(self, params):
|
||||
# settings
|
||||
self.curr_distro = params["distro"]
|
||||
@@ -171,12 +103,15 @@ class Configuration:
|
||||
# proxy settings
|
||||
self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" or params["ftp_proxy"] != "" \
|
||||
or params["git_proxy_host"] != "" or params["git_proxy_port"] != "" \
|
||||
or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
|
||||
self.split_proxy("http", params["http_proxy"])
|
||||
self.split_proxy("https", params["https_proxy"])
|
||||
self.split_proxy("ftp", params["ftp_proxy"])
|
||||
self.split_proxy("git", params["git_proxy_host"] + ":" + params["git_proxy_port"])
|
||||
self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
|
||||
or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != "" or params["all_proxy"] != ""
|
||||
self.all_proxy = params["all_proxy"]
|
||||
self.http_proxy = params["http_proxy"]
|
||||
self.ftp_proxy = params["ftp_proxy"]
|
||||
self.https_proxy = params["https_proxy"]
|
||||
self.git_proxy_host = params["git_proxy_host"]
|
||||
self.git_proxy_port = params["git_proxy_port"]
|
||||
self.cvs_proxy_host = params["cvs_proxy_host"]
|
||||
self.cvs_proxy_port = params["cvs_proxy_port"]
|
||||
|
||||
def load(self, template):
|
||||
self.curr_mach = template.getVar("MACHINE")
|
||||
@@ -217,15 +152,16 @@ class Configuration:
|
||||
self.selected_packages = template.getVar("IMAGE_INSTALL").split()
|
||||
# proxy
|
||||
self.enable_proxy = eval(template.getVar("enable_proxy"))
|
||||
self.same_proxy = eval(template.getVar("use_same_proxy"))
|
||||
self.split_proxy("http", template.getVar("http_proxy"))
|
||||
self.split_proxy("https", template.getVar("https_proxy"))
|
||||
self.split_proxy("ftp", template.getVar("ftp_proxy"))
|
||||
self.split_proxy("git", template.getVar("GIT_PROXY_HOST") + ":" + template.getVar("GIT_PROXY_PORT"))
|
||||
self.split_proxy("cvs", template.getVar("CVS_PROXY_HOST") + ":" + template.getVar("CVS_PROXY_PORT"))
|
||||
self.all_proxy = template.getVar("all_proxy")
|
||||
self.http_proxy = template.getVar("http_proxy")
|
||||
self.ftp_proxy = template.getVar("ftp_proxy")
|
||||
self.https_proxy = template.getVar("https_proxy")
|
||||
self.git_proxy_host = template.getVar("GIT_PROXY_HOST")
|
||||
self.git_proxy_port = template.getVar("GIT_PROXY_PORT")
|
||||
self.cvs_proxy_host = template.getVar("CVS_PROXY_HOST")
|
||||
self.cvs_proxy_port = template.getVar("CVS_PROXY_PORT")
|
||||
|
||||
def save(self, template, defaults=False):
|
||||
template.setVar("VERSION", "%s" % hobVer)
|
||||
# bblayers.conf
|
||||
template.setVar("BBLAYERS", " ".join(self.layers))
|
||||
# local.conf
|
||||
@@ -254,14 +190,14 @@ class Configuration:
|
||||
template.setVar("IMAGE_INSTALL", self.user_selected_packages)
|
||||
# proxy
|
||||
template.setVar("enable_proxy", self.enable_proxy)
|
||||
template.setVar("use_same_proxy", self.same_proxy)
|
||||
template.setVar("http_proxy", self.combine_proxy("http"))
|
||||
template.setVar("https_proxy", self.combine_proxy("https"))
|
||||
template.setVar("ftp_proxy", self.combine_proxy("ftp"))
|
||||
template.setVar("GIT_PROXY_HOST", self.combine_host_only("git"))
|
||||
template.setVar("GIT_PROXY_PORT", self.combine_port_only("git"))
|
||||
template.setVar("CVS_PROXY_HOST", self.combine_host_only("cvs"))
|
||||
template.setVar("CVS_PROXY_PORT", self.combine_port_only("cvs"))
|
||||
template.setVar("all_proxy", self.all_proxy)
|
||||
template.setVar("http_proxy", self.http_proxy)
|
||||
template.setVar("ftp_proxy", self.ftp_proxy)
|
||||
template.setVar("https_proxy", self.https_proxy)
|
||||
template.setVar("GIT_PROXY_HOST", self.git_proxy_host)
|
||||
template.setVar("GIT_PROXY_PORT", self.git_proxy_port)
|
||||
template.setVar("CVS_PROXY_HOST", self.cvs_proxy_host)
|
||||
template.setVar("CVS_PROXY_PORT", self.cvs_proxy_port)
|
||||
|
||||
class Parameters:
|
||||
'''Represents other variables like available machines, etc.'''
|
||||
@@ -283,8 +219,6 @@ class Parameters:
|
||||
self.all_sdk_machines = []
|
||||
self.all_layers = []
|
||||
self.image_names = []
|
||||
self.image_white_pattern = ""
|
||||
self.image_black_pattern = ""
|
||||
|
||||
# for build log to show
|
||||
self.bb_version = ""
|
||||
@@ -302,9 +236,6 @@ class Parameters:
|
||||
self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
|
||||
self.deployable_image_types = params["deployable_image_types"].split()
|
||||
self.tmpdir = params["tmpdir"]
|
||||
self.image_white_pattern = params["image_white_pattern"]
|
||||
self.image_black_pattern = params["image_black_pattern"]
|
||||
self.kernel_image_type = params["kernel_image_type"]
|
||||
# for build log to show
|
||||
self.bb_version = params["bb_version"]
|
||||
self.target_arch = params["target_arch"]
|
||||
@@ -376,15 +307,6 @@ class Builder(gtk.Window):
|
||||
END_NOOP : None,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def interpret_markup(cls, msg):
|
||||
msg = msg.replace('&', '&')
|
||||
msg = msg.replace('<', '<')
|
||||
msg = msg.replace('>', '>')
|
||||
msg = msg.replace('"', '"')
|
||||
msg = msg.replace("'", "´")
|
||||
return msg
|
||||
|
||||
def __init__(self, hobHandler, recipe_model, package_model):
|
||||
super(Builder, self).__init__()
|
||||
|
||||
@@ -396,11 +318,6 @@ class Builder(gtk.Window):
|
||||
|
||||
self.template = None
|
||||
|
||||
# logger
|
||||
self.logger = logging.getLogger("BitBake")
|
||||
self.consolelog = None
|
||||
self.current_logfile = None
|
||||
|
||||
# configuration and parameters
|
||||
self.configuration = Configuration()
|
||||
self.parameters = Parameters()
|
||||
@@ -436,10 +353,8 @@ class Builder(gtk.Window):
|
||||
self.handler.build.connect("build-started", self.handler_build_started_cb)
|
||||
self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
|
||||
self.handler.build.connect("build-failed", self.handler_build_failed_cb)
|
||||
self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
|
||||
self.handler.build.connect("task-started", self.handler_task_started_cb)
|
||||
self.handler.build.connect("log-error", self.handler_build_failure_cb)
|
||||
self.handler.build.connect("log", self.handler_build_log_cb)
|
||||
self.handler.build.connect("no-provider", self.handler_no_provider_cb)
|
||||
self.handler.connect("generating-data", self.handler_generating_data_cb)
|
||||
self.handler.connect("data-generated", self.handler_data_generated_cb)
|
||||
@@ -489,7 +404,7 @@ class Builder(gtk.Window):
|
||||
|
||||
def initiate_new_build_async(self):
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
if self.load_template(TemplateMgr.convert_to_template_pathfilename("default", ".hob/")) == False:
|
||||
if self.load_template(TemplateMgr.convert_to_template_pathfilename("default", ".hob/")) == None:
|
||||
self.handler.init_cooker()
|
||||
self.handler.set_extra_inherit("image_types")
|
||||
self.handler.generate_configuration()
|
||||
@@ -508,40 +423,31 @@ class Builder(gtk.Window):
|
||||
self.set_user_config()
|
||||
self.handler.generate_recipes()
|
||||
|
||||
def generate_packages_async(self, log = False):
|
||||
def generate_packages_async(self):
|
||||
self.switch_page(self.PACKAGE_GENERATING)
|
||||
if log:
|
||||
self.current_logfile = self.handler.get_logfile()
|
||||
self.do_log(self.current_logfile)
|
||||
# Build packages
|
||||
_, all_recipes = self.recipe_model.get_selected_recipes()
|
||||
self.set_user_config()
|
||||
self.handler.reset_build()
|
||||
self.handler.generate_packages(all_recipes, self.configuration.default_task)
|
||||
|
||||
def fast_generate_image_async(self, log = False):
|
||||
def fast_generate_image_async(self):
|
||||
self.switch_page(self.FAST_IMAGE_GENERATING)
|
||||
if log:
|
||||
self.current_logfile = self.handler.get_logfile()
|
||||
self.do_log(self.current_logfile)
|
||||
# Build packages
|
||||
_, all_recipes = self.recipe_model.get_selected_recipes()
|
||||
self.set_user_config()
|
||||
self.handler.reset_build()
|
||||
self.handler.generate_packages(all_recipes, self.configuration.default_task)
|
||||
|
||||
def generate_image_async(self, cont = False):
|
||||
def generate_image_async(self):
|
||||
self.switch_page(self.IMAGE_GENERATING)
|
||||
self.handler.reset_build()
|
||||
if not cont:
|
||||
self.current_logfile = self.handler.get_logfile()
|
||||
self.do_log(self.current_logfile)
|
||||
# Build image
|
||||
self.set_user_config()
|
||||
toolchain_packages = []
|
||||
if self.configuration.toolchain_build:
|
||||
toolchain_packages = self.package_model.get_selected_packages_toolchain()
|
||||
if self.configuration.selected_image == self.recipe_model.__custom_image__:
|
||||
if self.configuration.selected_image == self.recipe_model.__dummy_image__:
|
||||
packages = self.package_model.get_selected_packages()
|
||||
image = self.hob_image
|
||||
else:
|
||||
@@ -567,16 +473,9 @@ class Builder(gtk.Window):
|
||||
|
||||
def load_template(self, path):
|
||||
if not os.path.isfile(path):
|
||||
return False
|
||||
return None
|
||||
|
||||
self.template = TemplateMgr()
|
||||
# check compatibility
|
||||
tempVer = self.template.getVersion(path)
|
||||
if not tempVer or int(tempVer) < hobVer:
|
||||
self.template.destroy()
|
||||
self.template = None
|
||||
return False
|
||||
|
||||
try:
|
||||
self.template.load(path)
|
||||
self.configuration.load(self.template)
|
||||
@@ -643,14 +542,14 @@ class Builder(gtk.Window):
|
||||
pass
|
||||
|
||||
elif next_step == self.PACKAGE_SELECTION:
|
||||
self.package_details_page.show_page(self.current_logfile)
|
||||
pass
|
||||
|
||||
elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
|
||||
# both PACKAGE_GENEATING and FAST_IMAGE_GENERATING share the same page
|
||||
self.build_details_page.show_page(next_step)
|
||||
|
||||
elif next_step == self.PACKAGE_GENERATED:
|
||||
self.package_details_page.show_page(self.current_logfile)
|
||||
pass
|
||||
|
||||
elif next_step == self.IMAGE_GENERATING:
|
||||
# after packages are generated, selected_packages need to
|
||||
@@ -689,17 +588,19 @@ class Builder(gtk.Window):
|
||||
self.handler.set_extra_inherit("image_types")
|
||||
# set proxies
|
||||
if self.configuration.enable_proxy == True:
|
||||
self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
|
||||
self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
|
||||
self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
|
||||
self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
|
||||
self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
|
||||
self.handler.set_http_proxy(self.configuration.http_proxy)
|
||||
self.handler.set_https_proxy(self.configuration.https_proxy)
|
||||
self.handler.set_ftp_proxy(self.configuration.ftp_proxy)
|
||||
self.handler.set_all_proxy(self.configuration.all_proxy)
|
||||
self.handler.set_git_proxy(self.configuration.git_proxy_host, self.configuration.git_proxy_port)
|
||||
self.handler.set_cvs_proxy(self.configuration.cvs_proxy_host, self.configuration.cvs_proxy_port)
|
||||
elif self.configuration.enable_proxy == False:
|
||||
self.handler.set_http_proxy("")
|
||||
self.handler.set_https_proxy("")
|
||||
self.handler.set_ftp_proxy("")
|
||||
self.handler.set_git_proxy("", "")
|
||||
self.handler.set_cvs_proxy("", "")
|
||||
self.handler.set_http_proxy('')
|
||||
self.handler.set_https_proxy('')
|
||||
self.handler.set_ftp_proxy('')
|
||||
self.handler.set_all_proxy('')
|
||||
self.handler.set_git_proxy('', '')
|
||||
self.handler.set_cvs_proxy('', '')
|
||||
|
||||
def update_recipe_model(self, selected_image, selected_recipes):
|
||||
self.recipe_model.set_selected_image(selected_image)
|
||||
@@ -752,11 +653,11 @@ class Builder(gtk.Window):
|
||||
|
||||
self.rcppkglist_populated()
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
self.generate_image_async(True)
|
||||
self.generate_image_async()
|
||||
|
||||
def show_error_dialog(self, msg):
|
||||
lbl = "<b>Error</b>\n"
|
||||
lbl = lbl + "%s\n\n" % Builder.interpret_markup(msg)
|
||||
lbl = lbl + "%s\n\n" % glib.markup_escape_text(msg)
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
@@ -775,9 +676,7 @@ class Builder(gtk.Window):
|
||||
|
||||
def window_sensitive(self, sensitive):
|
||||
self.image_configuration_page.machine_combo.set_sensitive(sensitive)
|
||||
self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
|
||||
self.image_configuration_page.image_combo.set_sensitive(sensitive)
|
||||
self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
|
||||
self.image_configuration_page.layer_button.set_sensitive(sensitive)
|
||||
self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
|
||||
self.image_configuration_page.toolbar.set_sensitive(sensitive)
|
||||
@@ -809,7 +708,7 @@ class Builder(gtk.Window):
|
||||
selected_packages = self.configuration.selected_packages[:]
|
||||
|
||||
self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
|
||||
self.image_configuration_page.update_image_desc()
|
||||
self.image_configuration_page.update_image_desc(selected_image)
|
||||
self.update_recipe_model(selected_image, selected_recipes)
|
||||
self.update_package_model(selected_packages)
|
||||
|
||||
@@ -879,7 +778,7 @@ class Builder(gtk.Window):
|
||||
fraction = 1.0
|
||||
self.parameters.image_names = []
|
||||
selected_image = self.recipe_model.get_selected_image()
|
||||
if selected_image == self.recipe_model.__custom_image__:
|
||||
if selected_image == self.recipe_model.__dummy_image__:
|
||||
linkname = 'hob-image-' + self.configuration.curr_mach
|
||||
else:
|
||||
linkname = selected_image + '-' + self.configuration.curr_mach
|
||||
@@ -905,20 +804,12 @@ class Builder(gtk.Window):
|
||||
message = "Build stopped: "
|
||||
fraction = self.build_details_page.progress_bar.get_fraction()
|
||||
else:
|
||||
fail_to_next_edit = ""
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
fail_to_next_edit = "image configuration"
|
||||
fraction = 0.9
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
if self.previous_step == self.FAST_IMAGE_GENERATING:
|
||||
fail_to_next_edit = "image configuration"
|
||||
else:
|
||||
fail_to_next_edit = "packages"
|
||||
fraction = 1.0
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
fail_to_next_edit = "recipes"
|
||||
fraction = 1.0
|
||||
self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0], fail_to_next_edit)
|
||||
status = "fail"
|
||||
message = "Build failed: "
|
||||
self.build_details_page.update_progress_bar(message, fraction, status)
|
||||
@@ -937,11 +828,8 @@ class Builder(gtk.Window):
|
||||
def handler_build_failed_cb(self, running_build):
|
||||
self.build_failed()
|
||||
|
||||
def handler_build_aborted_cb(self, running_build):
|
||||
self.build_failed()
|
||||
|
||||
def handler_no_provider_cb(self, running_build, msg):
|
||||
dialog = CrumbsMessageDialog(self, Builder.interpret_markup(msg), gtk.STOCK_DIALOG_INFO)
|
||||
dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.STOCK_DIALOG_INFO)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
@@ -979,10 +867,6 @@ class Builder(gtk.Window):
|
||||
def handler_build_failure_cb(self, running_build):
|
||||
self.build_details_page.show_issues()
|
||||
|
||||
def handler_build_log_cb(self, running_build, func, obj):
|
||||
if hasattr(self.logger, func):
|
||||
getattr(self.logger, func)(obj)
|
||||
|
||||
def destroy_window_cb(self, widget, event):
|
||||
if not self.sensitive:
|
||||
return True
|
||||
@@ -1012,7 +896,7 @@ class Builder(gtk.Window):
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
self.generate_packages_async(True)
|
||||
self.generate_packages_async()
|
||||
|
||||
def build_image(self):
|
||||
selected_packages = self.package_model.get_selected_packages()
|
||||
@@ -1025,14 +909,14 @@ class Builder(gtk.Window):
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
self.generate_image_async(True)
|
||||
self.generate_image_async()
|
||||
|
||||
def just_bake(self):
|
||||
selected_image = self.recipe_model.get_selected_image()
|
||||
selected_packages = self.package_model.get_selected_packages() or []
|
||||
|
||||
# If no base image and no selected packages don't build anything
|
||||
if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
|
||||
if not (selected_packages or selected_image != self.recipe_model.__dummy_image__):
|
||||
lbl = "<b>No selections made</b>\nYou have not made any selections"
|
||||
lbl = lbl + " so there isn't anything to bake at this time."
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
@@ -1042,7 +926,7 @@ class Builder(gtk.Window):
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
self.fast_generate_image_async(True)
|
||||
self.fast_generate_image_async()
|
||||
|
||||
def show_binb_dialog(self, binb):
|
||||
markup = "<b>Brought in by:</b>\n%s" % binb
|
||||
@@ -1187,7 +1071,16 @@ class Builder(gtk.Window):
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def show_load_kernel_dialog(self):
|
||||
def runqemu_image(self, image_name):
|
||||
if not image_name:
|
||||
lbl = "<b>Please select an image to launch in QEMU.</b>"
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
dialog = gtk.FileChooserDialog("Load Kernel Files", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
@@ -1202,50 +1095,35 @@ class Builder(gtk.Window):
|
||||
dialog.set_current_folder(self.parameters.image_addr)
|
||||
|
||||
response = dialog.run()
|
||||
kernel_path = ""
|
||||
if response == gtk.RESPONSE_YES:
|
||||
kernel_path = dialog.get_filename()
|
||||
|
||||
image_path = os.path.join(self.parameters.image_addr, image_name)
|
||||
dialog.destroy()
|
||||
|
||||
return kernel_path
|
||||
|
||||
def runqemu_image(self, image_name, kernel_name):
|
||||
if not image_name or not kernel_name:
|
||||
lbl = "<b>Please select an %s to launch in QEMU.</b>" % ("kernel" if image_name else "image")
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
return
|
||||
|
||||
kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
|
||||
image_path = os.path.join(self.parameters.image_addr, image_name)
|
||||
|
||||
source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
|
||||
tmp_path = self.parameters.tmpdir
|
||||
cmdline = bb.ui.crumbs.utils.which_terminal()
|
||||
if os.path.exists(image_path) and os.path.exists(kernel_path) \
|
||||
and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
|
||||
and cmdline:
|
||||
cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
|
||||
cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
|
||||
cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
|
||||
subprocess.Popen(shlex.split(cmdline))
|
||||
else:
|
||||
lbl = "<b>Path error</b>\nOne of your paths is wrong,"
|
||||
lbl = lbl + " please make sure the following paths exist:\n"
|
||||
lbl = lbl + "image path:" + image_path + "\n"
|
||||
lbl = lbl + "kernel path:" + kernel_path + "\n"
|
||||
lbl = lbl + "source environment path:" + source_env_path + "\n"
|
||||
lbl = lbl + "tmp path: " + tmp_path + "."
|
||||
lbl = lbl + "You may be missing either xterm or vte for terminal services."
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
|
||||
tmp_path = self.parameters.tmpdir
|
||||
cmdline = bb.ui.crumbs.utils.which_terminal()
|
||||
if os.path.exists(image_path) and os.path.exists(kernel_path) \
|
||||
and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
|
||||
and cmdline:
|
||||
cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
|
||||
cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
|
||||
cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
|
||||
subprocess.Popen(shlex.split(cmdline))
|
||||
else:
|
||||
lbl = "<b>Path error</b>\nOne of your paths is wrong,"
|
||||
lbl = lbl + " please make sure the following paths exist:\n"
|
||||
lbl = lbl + "image path:" + image_path + "\n"
|
||||
lbl = lbl + "kernel path:" + kernel_path + "\n"
|
||||
lbl = lbl + "source environment path:" + source_env_path + "\n"
|
||||
lbl = lbl + "tmp path: " + tmp_path + "."
|
||||
lbl = lbl + "You may be missing either xterm or vte for terminal services."
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def show_packages(self, ask=True):
|
||||
_, selected_recipes = self.recipe_model.get_selected_recipes()
|
||||
@@ -1261,7 +1139,7 @@ class Builder(gtk.Window):
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.generate_packages_async(True)
|
||||
self.generate_packages_async()
|
||||
else:
|
||||
self.switch_page(self.PACKAGE_SELECTION)
|
||||
else:
|
||||
@@ -1309,15 +1187,3 @@ class Builder(gtk.Window):
|
||||
self.cancel_build_sync()
|
||||
elif response == gtk.RESPONSE_YES:
|
||||
self.cancel_build_sync(True)
|
||||
|
||||
def do_log(self, consolelogfile = None):
|
||||
if consolelogfile:
|
||||
if self.consolelog:
|
||||
self.logger.removeHandler(self.consolelog)
|
||||
self.consolelog = None
|
||||
self.consolelog = logging.FileHandler(consolelogfile)
|
||||
bb.msg.addDefaultlogFilter(self.consolelog)
|
||||
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
|
||||
self.consolelog.setFormatter(format)
|
||||
|
||||
self.logger.addHandler(self.consolelog)
|
||||
@@ -20,20 +20,17 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import glob
|
||||
import gtk
|
||||
import gobject
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import tempfile
|
||||
import shlex
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hcc, hic, HobViewTable, HobInfoButton, HobButton, HobAltButton, HobIconChecker
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
import bb.ui.crumbs.utils
|
||||
import bb.process
|
||||
|
||||
"""
|
||||
The following are convenience classes for implementing GNOME HIG compliant
|
||||
@@ -66,7 +63,7 @@ class CrumbsMessageDialog(CrumbsDialog):
|
||||
"""
|
||||
def __init__(self, parent=None, label="", icon=gtk.STOCK_INFO):
|
||||
super(CrumbsMessageDialog, self).__init__("", parent, gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
|
||||
|
||||
self.set_border_width(6)
|
||||
self.vbox.set_property("spacing", 12)
|
||||
self.action_area.set_property("spacing", 12)
|
||||
@@ -140,8 +137,6 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
def entry_widget_select_path_cb(self, action, parent, entry):
|
||||
dialog = gtk.FileChooserDialog("", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||
text = entry.get_text()
|
||||
dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Open", gtk.RESPONSE_YES)
|
||||
@@ -177,45 +172,6 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
hbox.show_all()
|
||||
return hbox, entry
|
||||
|
||||
def details_cb(self, button, parent, protocol):
|
||||
dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
|
||||
user = self.configuration.proxies[protocol][1],
|
||||
passwd = self.configuration.proxies[protocol][2],
|
||||
parent = parent,
|
||||
flags = gtk.DIALOG_MODAL
|
||||
| gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR)
|
||||
dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
|
||||
response = dialog.run()
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.configuration.proxies[protocol][1] = dialog.user
|
||||
self.configuration.proxies[protocol][2] = dialog.passwd
|
||||
self.refresh_proxy_components()
|
||||
dialog.destroy()
|
||||
|
||||
def gen_proxy_entry_widget(self, protocol, parent, need_button=True):
|
||||
hbox = gtk.HBox(False, 12)
|
||||
|
||||
label = gtk.Label(protocol.upper() + " proxy")
|
||||
hbox.pack_start(label, expand=True, fill=False, padding=24)
|
||||
|
||||
proxy_entry = gtk.Entry()
|
||||
proxy_entry.set_size_request(300, -1)
|
||||
hbox.pack_start(proxy_entry, expand=False, fill=False)
|
||||
|
||||
hbox.pack_start(gtk.Label(":"), expand=False, fill=False)
|
||||
|
||||
port_entry = gtk.Entry()
|
||||
port_entry.set_size_request(60, -1)
|
||||
hbox.pack_start(port_entry, expand=False, fill=False)
|
||||
|
||||
details_button = HobAltButton("Details")
|
||||
details_button.connect("clicked", self.details_cb, parent, protocol)
|
||||
hbox.pack_start(details_button, expand=False, fill=False)
|
||||
|
||||
hbox.show_all()
|
||||
return hbox, proxy_entry, port_entry, details_button
|
||||
|
||||
def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
|
||||
combo_item = self.rootfs_combo.get_active_text()
|
||||
for child in check_hbox.get_children():
|
||||
@@ -401,8 +357,14 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
data += ("IMAGE_FSTYPES: " + self._get_sorted_value(self.configuration.image_fstypes))
|
||||
data += ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy))
|
||||
if self.configuration.enable_proxy:
|
||||
for protocol in self.configuration.proxies.keys():
|
||||
data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol)))
|
||||
data += ("ALL_PROXY: " + self._get_sorted_value(self.configuration.all_proxy))
|
||||
data += ("HTTP_PROXY: " + self._get_sorted_value(self.configuration.http_proxy))
|
||||
data += ("HTTPS_PROXY: " + self._get_sorted_value(self.configuration.https_proxy))
|
||||
data += ("FTP_PROXY: " + self._get_sorted_value(self.configuration.ftp_proxy))
|
||||
data += ("GIT_PROXY_HOST: " + self._get_sorted_value(self.configuration.git_proxy_host))
|
||||
data += ("GIT_PROXY_PORT: " + self._get_sorted_value(self.configuration.git_proxy_port))
|
||||
data += ("CVS_PROXY_HOST: " + self._get_sorted_value(self.configuration.cvs_proxy_host))
|
||||
data += ("CVS_PROXY_PORT: " + self._get_sorted_value(self.configuration.cvs_proxy_port))
|
||||
for key in self.configuration.extra_setting.keys():
|
||||
data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key]))
|
||||
return hashlib.md5(data).hexdigest()
|
||||
@@ -567,56 +529,60 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
|
||||
sub_vbox = gtk.VBox(False, 6)
|
||||
advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set the proxies that will be used during fetching source code</span>")
|
||||
tooltip = "Set the proxies that will be used during fetching source code or set none for direct the Internet connection"
|
||||
info = HobInfoButton(tooltip, self)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.pack_start(label, expand=True, fill=True)
|
||||
hbox.pack_start(info, expand=False, fill=False)
|
||||
sub_vbox.pack_start(hbox, expand=False, fill=False)
|
||||
|
||||
self.direct_checkbox = gtk.RadioButton(None, "Direct internet connection")
|
||||
self.direct_checkbox.set_tooltip_text("Check this box to connect the Internet directly without any proxy")
|
||||
self.direct_checkbox.set_active(not self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False)
|
||||
|
||||
self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration")
|
||||
self.proxy_checkbox = gtk.CheckButton("Enable proxy")
|
||||
self.proxy_checkbox.set_tooltip_text("Check this box to setup the proxy you specified")
|
||||
self.proxy_checkbox.set_active(self.configuration.enable_proxy)
|
||||
self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
|
||||
sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False)
|
||||
|
||||
self.same_checkbox = gtk.CheckButton("Use the same proxy for all protocols")
|
||||
self.same_checkbox.set_tooltip_text("Use the same proxy as the first proxy i.e. http proxy for all protocols")
|
||||
self.same_checkbox.set_active(self.configuration.same_proxy)
|
||||
hbox = gtk.HBox(False, 12)
|
||||
hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24)
|
||||
sub_vbox.pack_start(hbox, expand=False, fill=False)
|
||||
|
||||
proxy_widget, self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget(
|
||||
"http", self, True)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set all proxy:</span>")
|
||||
tooltip = "Set the all proxy that will be used if the proxy for a URL isn't specified."
|
||||
proxy_widget, self.all_proxy_text = self.gen_entry_widget(self.configuration.all_proxy, self, tooltip, False)
|
||||
self.all_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.all_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
proxy_widget, self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget(
|
||||
"https", self, True)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set http proxy:</span>")
|
||||
tooltip = "Set the http proxy that will be used in do_fetch() source code"
|
||||
proxy_widget, self.http_proxy_text = self.gen_entry_widget(self.configuration.http_proxy, self, tooltip, False)
|
||||
self.http_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.http_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
proxy_widget, self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget(
|
||||
"ftp", self, True)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set https proxy:</span>")
|
||||
tooltip = "Set the https proxy that will be used in do_fetch() source code"
|
||||
proxy_widget, self.https_proxy_text = self.gen_entry_widget(self.configuration.https_proxy, self, tooltip, False)
|
||||
self.https_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.https_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
proxy_widget, self.git_proxy, self.git_proxy_port, self.git_proxy_details = self.gen_proxy_entry_widget(
|
||||
"git", self, True)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set ftp proxy:</span>")
|
||||
tooltip = "Set the ftp proxy that will be used in do_fetch() source code"
|
||||
proxy_widget, self.ftp_proxy_text = self.gen_entry_widget(self.configuration.ftp_proxy, self, tooltip, False)
|
||||
self.ftp_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.ftp_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
proxy_widget, self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget(
|
||||
"cvs", self, True)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set git proxy:</span>")
|
||||
tooltip = "Set the git proxy that will be used in do_fetch() source code"
|
||||
proxy_widget, self.git_proxy_text = self.gen_entry_widget(self.configuration.git_proxy_host + ':' + self.configuration.git_proxy_port, self, tooltip, False)
|
||||
self.git_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.git_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
|
||||
self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
|
||||
self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb)
|
||||
label = self.gen_label_widget("<span weight=\"bold\">Set cvs proxy:</span>")
|
||||
tooltip = "Set the cvs proxy that will be used in do_fetch() source code"
|
||||
proxy_widget, self.cvs_proxy_text = self.gen_entry_widget(self.configuration.cvs_proxy_host + ':' + self.configuration.cvs_proxy_port, self, tooltip, False)
|
||||
self.cvs_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.cvs_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
sub_vbox.pack_start(label, expand=False, fill=False)
|
||||
sub_vbox.pack_start(proxy_widget, expand=False, fill=False)
|
||||
|
||||
self.refresh_proxy_components()
|
||||
return advanced_vbox
|
||||
|
||||
def create_others_page(self):
|
||||
@@ -633,59 +599,20 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
|
||||
return advanced_vbox
|
||||
|
||||
def refresh_proxy_components(self):
|
||||
self.same_checkbox.set_sensitive(self.configuration.enable_proxy)
|
||||
|
||||
self.http_proxy.set_text(self.configuration.combine_host_only("http"))
|
||||
self.http_proxy.set_editable(self.configuration.enable_proxy)
|
||||
self.http_proxy.set_sensitive(self.configuration.enable_proxy)
|
||||
self.http_proxy_port.set_text(self.configuration.combine_port_only("http"))
|
||||
self.http_proxy_port.set_editable(self.configuration.enable_proxy)
|
||||
self.http_proxy_port.set_sensitive(self.configuration.enable_proxy)
|
||||
self.http_proxy_details.set_sensitive(self.configuration.enable_proxy)
|
||||
|
||||
self.https_proxy.set_text(self.configuration.combine_host_only("https"))
|
||||
self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.https_proxy_port.set_text(self.configuration.combine_port_only("https"))
|
||||
self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
|
||||
self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp"))
|
||||
self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp"))
|
||||
self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
|
||||
self.git_proxy.set_text(self.configuration.combine_host_only("git"))
|
||||
self.git_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.git_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.git_proxy_port.set_text(self.configuration.combine_port_only("git"))
|
||||
self.git_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.git_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.git_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
|
||||
self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs"))
|
||||
self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs"))
|
||||
self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
|
||||
|
||||
def proxy_checkbox_toggled_cb(self, button):
|
||||
self.configuration.enable_proxy = self.proxy_checkbox.get_active()
|
||||
if not self.configuration.enable_proxy:
|
||||
self.configuration.same_proxy = False
|
||||
self.same_checkbox.set_active(self.configuration.same_proxy)
|
||||
self.refresh_proxy_components()
|
||||
|
||||
def same_checkbox_toggled_cb(self, button):
|
||||
self.configuration.same_proxy = self.same_checkbox.get_active()
|
||||
self.refresh_proxy_components()
|
||||
self.all_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.all_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
self.http_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.http_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
self.https_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.https_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
self.ftp_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.ftp_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
self.git_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.git_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
self.cvs_proxy_text.set_editable(self.configuration.enable_proxy)
|
||||
self.cvs_proxy_text.set_sensitive(self.configuration.enable_proxy)
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
package_format = []
|
||||
@@ -729,17 +656,12 @@ class AdvancedSettingDialog (CrumbsDialog):
|
||||
self.configuration.extra_setting[key] = value
|
||||
it = self.setting_store.iter_next(it)
|
||||
|
||||
self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
|
||||
if self.configuration.same_proxy:
|
||||
self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
|
||||
self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
|
||||
self.configuration.split_proxy("git", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
|
||||
self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
|
||||
else:
|
||||
self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text())
|
||||
self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text())
|
||||
self.configuration.split_proxy("git", self.git_proxy.get_text() + ":" + self.git_proxy_port.get_text())
|
||||
self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text())
|
||||
self.configuration.all_proxy = self.all_proxy_text.get_text()
|
||||
self.configuration.http_proxy = self.http_proxy_text.get_text()
|
||||
self.configuration.https_proxy = self.https_proxy_text.get_text()
|
||||
self.configuration.ftp_proxy = self.ftp_proxy_text.get_text()
|
||||
self.configuration.git_proxy_host, self.configuration.git_proxy_port = self.git_proxy_text.get_text().split(':')
|
||||
self.configuration.cvs_proxy_host, self.configuration.cvs_proxy_port = self.cvs_proxy_text.get_text().split(':')
|
||||
|
||||
md5 = self.config_md5()
|
||||
self.settings_changed = (self.md5 != md5)
|
||||
@@ -751,28 +673,21 @@ class DeployImageDialog (CrumbsDialog):
|
||||
|
||||
__dummy_usb__ = "--select a usb drive--"
|
||||
|
||||
def __init__(self, title, image_path, parent, flags, buttons=None, standalone=False):
|
||||
def __init__(self, title, image_path, parent, flags, buttons=None):
|
||||
super(DeployImageDialog, self).__init__(title, parent, flags, buttons)
|
||||
|
||||
self.image_path = image_path
|
||||
self.standalone = standalone
|
||||
|
||||
self.create_visual_elements()
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.set_size_request(600, 400)
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
markup = "<span font_desc='12'>The image to be written into usb drive:</span>"
|
||||
label.set_markup(markup)
|
||||
self.vbox.pack_start(label, expand=False, fill=False, padding=2)
|
||||
|
||||
table = gtk.Table(2, 10, False)
|
||||
table.set_col_spacings(5)
|
||||
table.set_row_spacings(5)
|
||||
self.vbox.pack_start(table, expand=True, fill=True)
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
|
||||
scroll.set_shadow_type(gtk.SHADOW_IN)
|
||||
@@ -780,31 +695,11 @@ class DeployImageDialog (CrumbsDialog):
|
||||
tv.set_editable(False)
|
||||
tv.set_wrap_mode(gtk.WRAP_WORD)
|
||||
tv.set_cursor_visible(False)
|
||||
self.buf = gtk.TextBuffer()
|
||||
self.buf.set_text(self.image_path)
|
||||
tv.set_buffer(self.buf)
|
||||
buf = gtk.TextBuffer()
|
||||
buf.set_text(self.image_path)
|
||||
tv.set_buffer(buf)
|
||||
scroll.add(tv)
|
||||
table.attach(scroll, 0, 10, 0, 1)
|
||||
|
||||
# There are 2 ways to use DeployImageDialog
|
||||
# One way is that called by HOB when the 'Deploy Image' button is clicked
|
||||
# The other way is that called by a standalone script.
|
||||
# Following block of codes handles the latter way. It adds a 'Select Image' button and
|
||||
# emit a signal when the button is clicked.
|
||||
if self.standalone:
|
||||
gobject.signal_new("select_image_clicked", self, gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, ())
|
||||
icon = gtk.Image()
|
||||
pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_IMAGES_DISPLAY_FILE)
|
||||
icon.set_from_pixbuf(pix_buffer)
|
||||
button = gtk.Button("Select Image")
|
||||
button.set_image(icon)
|
||||
button.set_size_request(140, 50)
|
||||
table.attach(button, 9, 10, 1, 2, gtk.FILL, 0, 0, 0)
|
||||
button.connect("clicked", self.select_image_button_clicked_cb)
|
||||
|
||||
separator = gtk.HSeparator()
|
||||
self.vbox.pack_start(separator, expand=False, fill=False, padding=10)
|
||||
self.vbox.pack_start(scroll, expand=True, fill=True)
|
||||
|
||||
self.usb_desc = gtk.Label()
|
||||
self.usb_desc.set_alignment(0.0, 0.5)
|
||||
@@ -819,7 +714,7 @@ class DeployImageDialog (CrumbsDialog):
|
||||
for usb in self.find_all_usb_devices():
|
||||
self.usb_combo.append_text("/dev/" + usb)
|
||||
self.usb_combo.set_active(0)
|
||||
self.vbox.pack_start(self.usb_combo, expand=False, fill=False)
|
||||
self.vbox.pack_start(self.usb_combo, expand=True, fill=True)
|
||||
self.vbox.pack_start(self.usb_desc, expand=False, fill=False, padding=2)
|
||||
|
||||
self.progress_bar = HobProgressBar()
|
||||
@@ -830,19 +725,12 @@ class DeployImageDialog (CrumbsDialog):
|
||||
self.vbox.show_all()
|
||||
self.progress_bar.hide()
|
||||
|
||||
def set_image_text_buffer(self, image_path):
|
||||
self.buf.set_text(image_path)
|
||||
|
||||
def set_image_path(self, image_path):
|
||||
self.image_path = image_path
|
||||
|
||||
def popen_read(self, cmd):
|
||||
tmpout, errors = bb.process.run("%s" % cmd)
|
||||
return tmpout.strip()
|
||||
return os.popen("%s 2>/dev/null" % cmd).read().strip()
|
||||
|
||||
def find_all_usb_devices(self):
|
||||
usb_devs = [ os.readlink(u)
|
||||
for u in glob.glob('/dev/disk/by-id/usb*')
|
||||
for u in self.popen_read('ls /dev/disk/by-id/usb*').split()
|
||||
if not re.search(r'part\d+', u) ]
|
||||
return [ '%s' % u[u.rfind('/')+1:] for u in usb_devs ]
|
||||
|
||||
@@ -851,9 +739,6 @@ class DeployImageDialog (CrumbsDialog):
|
||||
(self.popen_read('cat /sys/class/block/%s/device/vendor' % dev),
|
||||
self.popen_read('cat /sys/class/block/%s/device/model' % dev))
|
||||
|
||||
def select_image_button_clicked_cb(self, button):
|
||||
self.emit('select_image_clicked')
|
||||
|
||||
def usb_combo_changed_cb(self, usb_combo):
|
||||
combo_item = self.usb_combo.get_active_text()
|
||||
if not combo_item or combo_item == self.__dummy_usb__:
|
||||
@@ -865,32 +750,12 @@ class DeployImageDialog (CrumbsDialog):
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
if response_id == gtk.RESPONSE_YES:
|
||||
lbl = ''
|
||||
combo_item = self.usb_combo.get_active_text()
|
||||
if combo_item and combo_item != self.__dummy_usb__ and self.image_path:
|
||||
if combo_item and combo_item != self.__dummy_usb__:
|
||||
cmdline = bb.ui.crumbs.utils.which_terminal()
|
||||
if cmdline:
|
||||
tmpfile = tempfile.NamedTemporaryFile()
|
||||
cmdline += "\"sudo dd if=" + self.image_path + \
|
||||
" of=" + combo_item + "; echo $? > " + tmpfile.name + "\""
|
||||
subprocess.call(shlex.split(cmdline))
|
||||
|
||||
if int(tmpfile.readline().strip()) == 0:
|
||||
lbl = "<b>Deploy image successfully.</b>"
|
||||
else:
|
||||
lbl = "<b>Failed to deploy image.</b>\nPlease check image <b>%s</b> exists and USB device <b>%s</b> is writable." % (self.image_path, combo_item)
|
||||
tmpfile.close()
|
||||
else:
|
||||
if not self.image_path:
|
||||
lbl = "<b>No selection made.</b>\nYou have not selected an image to deploy."
|
||||
else:
|
||||
lbl = "<b>No selection made.</b>\nYou have not selected a USB device."
|
||||
if len(lbl):
|
||||
crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
crumbs_dialog.run()
|
||||
crumbs_dialog.destroy()
|
||||
cmdline += "\"sudo dd if=" + self.image_path + " of=" + combo_item + "\""
|
||||
subprocess.Popen(args=shlex.split(cmdline))
|
||||
|
||||
def update_progress_bar(self, title, fraction, status=None):
|
||||
self.progress_bar.update(fraction)
|
||||
@@ -1094,7 +959,7 @@ class LayerSelectionDialog (CrumbsDialog):
|
||||
# create visual elements on the dialog
|
||||
self.create_visual_elements()
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
|
||||
def create_visual_elements(self):
|
||||
layer_widget, self.layer_store = self.gen_layer_widget(self.layers, self.all_layers, self, None)
|
||||
layer_widget.set_size_request(450, 250)
|
||||
@@ -1208,13 +1073,12 @@ class ImageSelectionDialog (CrumbsDialog):
|
||||
self.image_table = HobViewTable(self.__columns__)
|
||||
self.image_table.set_size_request(-1, 300)
|
||||
self.image_table.connect("toggled", self.toggled_cb)
|
||||
self.image_table.connect_group_selection(self.table_selected_cb)
|
||||
self.image_table.connect("row-activated", self.row_actived_cb)
|
||||
self.vbox.pack_start(self.image_table, expand=True, fill=True)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def change_image_cb(self, model, path, columnid):
|
||||
def toggled_cb(self, table, cell, path, columnid, tree):
|
||||
model = tree.get_model()
|
||||
if not model:
|
||||
return
|
||||
iter = model.get_iter_first()
|
||||
@@ -1225,24 +1089,9 @@ class ImageSelectionDialog (CrumbsDialog):
|
||||
|
||||
model[path][columnid] = True
|
||||
|
||||
def toggled_cb(self, table, cell, path, columnid, tree):
|
||||
model = tree.get_model()
|
||||
self.change_image_cb(model, path, columnid)
|
||||
|
||||
def table_selected_cb(self, selection):
|
||||
model, paths = selection.get_selected_rows()
|
||||
if paths:
|
||||
self.change_image_cb(model, paths[0], 1)
|
||||
|
||||
def row_actived_cb(self, tab, model, path):
|
||||
self.change_image_cb(model, path, 1)
|
||||
self.emit('response', gtk.RESPONSE_YES)
|
||||
|
||||
def select_path_cb(self, action, parent, entry):
|
||||
dialog = gtk.FileChooserDialog("", parent,
|
||||
gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||
text = entry.get_text()
|
||||
dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Open", gtk.RESPONSE_YES)
|
||||
@@ -1269,7 +1118,7 @@ class ImageSelectionDialog (CrumbsDialog):
|
||||
if f.endswith('.' + real_image_type):
|
||||
imageset.add(f.rsplit('.' + real_image_type)[0].rsplit('.rootfs')[0])
|
||||
self.image_list.append(f)
|
||||
|
||||
|
||||
for image in imageset:
|
||||
self.image_store.set(self.image_store.append(), 0, image, 1, False)
|
||||
|
||||
@@ -1285,65 +1134,5 @@ class ImageSelectionDialog (CrumbsDialog):
|
||||
for f in self.image_list:
|
||||
if f.startswith(self.image_store[path][0] + '.'):
|
||||
self.image_names.append(f)
|
||||
break
|
||||
break
|
||||
iter = self.image_store.iter_next(iter)
|
||||
|
||||
class ProxyDetailsDialog (CrumbsDialog):
|
||||
|
||||
def __init__(self, title, user, passwd, parent, flags, buttons=None):
|
||||
super(ProxyDetailsDialog, self).__init__(title, parent, flags, buttons)
|
||||
self.connect("response", self.response_cb)
|
||||
|
||||
self.auth = not (user == None or passwd == None or user == "")
|
||||
self.user = user or ""
|
||||
self.passwd = passwd or ""
|
||||
|
||||
# create visual elements on the dialog
|
||||
self.create_visual_elements()
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.auth_checkbox = gtk.CheckButton("Use authentication")
|
||||
self.auth_checkbox.set_tooltip_text("Check this box to set the username and the password")
|
||||
self.auth_checkbox.set_active(self.auth)
|
||||
self.auth_checkbox.connect("toggled", self.auth_checkbox_toggled_cb)
|
||||
self.vbox.pack_start(self.auth_checkbox, expand=False, fill=False)
|
||||
|
||||
hbox = gtk.HBox(False, 6)
|
||||
self.user_label = gtk.Label("Username:")
|
||||
self.user_text = gtk.Entry()
|
||||
self.user_text.set_text(self.user)
|
||||
hbox.pack_start(self.user_label, expand=False, fill=False)
|
||||
hbox.pack_end(self.user_text, expand=False, fill=False)
|
||||
self.vbox.pack_start(hbox, expand=False, fill=False)
|
||||
|
||||
hbox = gtk.HBox(False, 6)
|
||||
self.passwd_label = gtk.Label("Password:")
|
||||
self.passwd_text = gtk.Entry()
|
||||
self.passwd_text.set_text(self.passwd)
|
||||
hbox.pack_start(self.passwd_label, expand=False, fill=False)
|
||||
hbox.pack_end(self.passwd_text, expand=False, fill=False)
|
||||
self.vbox.pack_start(hbox, expand=False, fill=False)
|
||||
|
||||
self.refresh_auth_components()
|
||||
self.show_all()
|
||||
|
||||
def refresh_auth_components(self):
|
||||
self.user_label.set_sensitive(self.auth)
|
||||
self.user_text.set_editable(self.auth)
|
||||
self.user_text.set_sensitive(self.auth)
|
||||
self.passwd_label.set_sensitive(self.auth)
|
||||
self.passwd_text.set_editable(self.auth)
|
||||
self.passwd_text.set_sensitive(self.auth)
|
||||
|
||||
def auth_checkbox_toggled_cb(self, button):
|
||||
self.auth = self.auth_checkbox.get_active()
|
||||
self.refresh_auth_components()
|
||||
|
||||
def response_cb(self, dialog, response_id):
|
||||
if response_id == gtk.RESPONSE_OK:
|
||||
if self.auth:
|
||||
self.user = self.user_text.get_text()
|
||||
self.passwd = self.passwd_text.get_text()
|
||||
else:
|
||||
self.user = None
|
||||
self.passwd = None
|
||||
|
||||
@@ -178,7 +178,9 @@ class HobHandler(gobject.GObject):
|
||||
|
||||
elif isinstance(event, logging.LogRecord):
|
||||
if event.levelno >= logging.ERROR:
|
||||
self.error_msg += event.msg + '\n'
|
||||
formatter = bb.msg.BBLogFormatter()
|
||||
formatter.format(event)
|
||||
self.error_msg += event.message + '\n'
|
||||
|
||||
elif isinstance(event, bb.event.TargetsTreeGenerated):
|
||||
self.current_phase = "data generation"
|
||||
@@ -318,6 +320,9 @@ class HobHandler(gobject.GObject):
|
||||
def set_ftp_proxy(self, ftp_proxy):
|
||||
self.runCommand(["setVariable", "ftp_proxy", ftp_proxy])
|
||||
|
||||
def set_all_proxy(self, all_proxy):
|
||||
self.runCommand(["setVariable", "all_proxy", all_proxy])
|
||||
|
||||
def set_git_proxy(self, host, port):
|
||||
self.runCommand(["setVariable", "GIT_PROXY_HOST", host])
|
||||
self.runCommand(["setVariable", "GIT_PROXY_PORT", port])
|
||||
@@ -347,7 +352,7 @@ class HobHandler(gobject.GObject):
|
||||
self.commands_async.append(self.SUB_PARSE_CONFIG)
|
||||
self.commands_async.append(self.SUB_GNERATE_TGTS)
|
||||
self.run_next_command(self.GENERATE_RECIPES)
|
||||
|
||||
|
||||
def generate_packages(self, tgts, default_task="build"):
|
||||
targets = []
|
||||
targets.extend(tgts)
|
||||
@@ -390,9 +395,6 @@ class HobHandler(gobject.GObject):
|
||||
def reset_build(self):
|
||||
self.build.reset()
|
||||
|
||||
def get_logfile(self):
|
||||
return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])
|
||||
|
||||
def _remove_redundant(self, string):
|
||||
ret = []
|
||||
for i in string.split():
|
||||
@@ -495,7 +497,6 @@ class HobHandler(gobject.GObject):
|
||||
params["runnable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_IMAGE_TYPES"]) or "")
|
||||
params["runnable_machine_patterns"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_MACHINE_PATTERNS"]) or "")
|
||||
params["deployable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "DEPLOYABLE_IMAGE_TYPES"]) or "")
|
||||
params["kernel_image_type"] = self.runCommand(["getVariable", "KERNEL_IMAGETYPE"]) or ""
|
||||
params["tmpdir"] = self.runCommand(["getVariable", "TMPDIR"]) or ""
|
||||
params["distro_version"] = self.runCommand(["getVariable", "DISTRO_VERSION"]) or ""
|
||||
params["target_os"] = self.runCommand(["getVariable", "TARGET_OS"]) or ""
|
||||
@@ -511,10 +512,9 @@ class HobHandler(gobject.GObject):
|
||||
params["http_proxy"] = self.runCommand(["getVariable", "http_proxy"]) or ""
|
||||
params["ftp_proxy"] = self.runCommand(["getVariable", "ftp_proxy"]) or ""
|
||||
params["https_proxy"] = self.runCommand(["getVariable", "https_proxy"]) or ""
|
||||
params["all_proxy"] = self.runCommand(["getVariable", "all_proxy"]) or ""
|
||||
|
||||
params["cvs_proxy_host"] = self.runCommand(["getVariable", "CVS_PROXY_HOST"]) or ""
|
||||
params["cvs_proxy_port"] = self.runCommand(["getVariable", "CVS_PROXY_PORT"]) or ""
|
||||
|
||||
params["image_white_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_WHITE_PATTERN"]) or ""
|
||||
params["image_black_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_BLACK_PATTERN"]) or ""
|
||||
return params
|
||||
|
||||
@@ -34,7 +34,7 @@ class PackageListModel(gtk.TreeStore):
|
||||
providing convenience functions to access gtk.TreeModel subclasses which
|
||||
provide filtered views of the data.
|
||||
"""
|
||||
(COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_BINB, COL_INC, COL_FADE_INC, COL_FONT) = range(13)
|
||||
(COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_BINB, COL_INC, COL_FADE_INC) = range(12)
|
||||
|
||||
__gsignals__ = {
|
||||
"package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
@@ -65,8 +65,7 @@ class PackageListModel(gtk.TreeStore):
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_STRING,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_BOOLEAN,
|
||||
gobject.TYPE_STRING)
|
||||
gobject.TYPE_BOOLEAN)
|
||||
|
||||
|
||||
"""
|
||||
@@ -190,7 +189,7 @@ class PackageListModel(gtk.TreeStore):
|
||||
self.COL_SEC, section, self.COL_SUM, summary,
|
||||
self.COL_RDEP, rdep + ' ' + rrec,
|
||||
self.COL_RPROV, rprov, self.COL_SIZE, size,
|
||||
self.COL_BINB, "", self.COL_INC, False, self.COL_FONT, '10')
|
||||
self.COL_BINB, "", self.COL_INC, False)
|
||||
|
||||
"""
|
||||
Check whether the item at item_path is included or not
|
||||
@@ -456,7 +455,7 @@ class RecipeListModel(gtk.ListStore):
|
||||
"""
|
||||
(COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN, COL_FADE_INC) = range(12)
|
||||
|
||||
__custom_image__ = "Create your own image"
|
||||
__dummy_image__ = "Create your own image"
|
||||
|
||||
__gsignals__ = {
|
||||
"recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
@@ -565,14 +564,14 @@ class RecipeListModel(gtk.ListStore):
|
||||
self.clear()
|
||||
|
||||
# dummy image for prompt
|
||||
self.set(self.append(), self.COL_NAME, self.__custom_image__,
|
||||
self.set(self.append(), self.COL_NAME, self.__dummy_image__,
|
||||
self.COL_DESC, "Use the 'View recipes' and 'View packages' " \
|
||||
"options to select what you want to include " \
|
||||
"in your image.",
|
||||
self.COL_LIC, "", self.COL_GROUP, "",
|
||||
self.COL_DEPS, "", self.COL_BINB, "",
|
||||
self.COL_TYPE, "image", self.COL_INC, False,
|
||||
self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, self.__custom_image__)
|
||||
self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, self.__dummy_image__)
|
||||
|
||||
for item in event_model["pn"]:
|
||||
name = item
|
||||
|
||||
@@ -23,7 +23,6 @@ import os
|
||||
import os.path
|
||||
import sys
|
||||
import pango, pangocairo
|
||||
import cairo
|
||||
import math
|
||||
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
@@ -89,7 +88,6 @@ class hcc:
|
||||
"cpio.xz" : ["cpio.xz"],
|
||||
"vmdk" : ["vmdk"],
|
||||
"cpio.lzma" : ["cpio.lzma"],
|
||||
"elf" : ["elf"],
|
||||
}
|
||||
|
||||
class HobViewTable (gtk.VBox):
|
||||
@@ -121,7 +119,6 @@ class HobViewTable (gtk.VBox):
|
||||
self.table_tree.set_headers_clickable(True)
|
||||
self.table_tree.set_enable_search(True)
|
||||
self.table_tree.set_rules_hint(True)
|
||||
self.table_tree.set_enable_tree_lines(True)
|
||||
self.table_tree.get_selection().set_mode(gtk.SELECTION_SINGLE)
|
||||
self.toggle_columns = []
|
||||
self.table_tree.connect("row-activated", self.row_activated_cb)
|
||||
@@ -143,8 +140,6 @@ class HobViewTable (gtk.VBox):
|
||||
cell = gtk.CellRendererText()
|
||||
col.pack_start(cell, True)
|
||||
col.set_attributes(cell, text=column['col_id'])
|
||||
if 'col_t_id' in column.keys():
|
||||
col.add_attribute(cell, 'font', column['col_t_id'])
|
||||
elif column['col_style'] == 'check toggle':
|
||||
cell = HobCellRendererToggle()
|
||||
cell.set_property('activatable', True)
|
||||
@@ -154,8 +149,6 @@ class HobViewTable (gtk.VBox):
|
||||
col.pack_end(cell, True)
|
||||
col.set_attributes(cell, active=column['col_id'])
|
||||
self.toggle_columns.append(column['col_name'])
|
||||
if 'col_group' in column.keys():
|
||||
col.set_cell_data_func(cell, self.set_group_number_cb)
|
||||
elif column['col_style'] == 'radio toggle':
|
||||
cell = gtk.CellRendererToggle()
|
||||
cell.set_property('activatable', True)
|
||||
@@ -169,8 +162,6 @@ class HobViewTable (gtk.VBox):
|
||||
cell = gtk.CellRendererText()
|
||||
col.pack_start(cell, True)
|
||||
col.set_cell_data_func(cell, self.display_binb_cb, column['col_id'])
|
||||
if 'col_t_id' in column.keys():
|
||||
col.add_attribute(cell, 'font', column['col_t_id'])
|
||||
|
||||
scroll = gtk.ScrolledWindow()
|
||||
scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
|
||||
@@ -213,15 +204,6 @@ class HobViewTable (gtk.VBox):
|
||||
def stop_cell_fadeinout_cb(self, ctrl, cell, tree):
|
||||
self.emit("cell-fadeinout-stopped", ctrl, cell, tree)
|
||||
|
||||
def set_group_number_cb(self, col, cell, model, iter):
|
||||
if model and (model.iter_parent(iter) == None):
|
||||
cell.cell_attr["number_of_children"] = model.iter_n_children(iter)
|
||||
else:
|
||||
cell.cell_attr["number_of_children"] = 0
|
||||
|
||||
def connect_group_selection(self, cb_func):
|
||||
self.table_tree.get_selection().connect("changed", cb_func)
|
||||
|
||||
"""
|
||||
A method to calculate a softened value for the colour of widget when in the
|
||||
provided state.
|
||||
@@ -398,95 +380,363 @@ class HobInfoButton(gtk.EventBox):
|
||||
def mouse_out_cb(self, widget, event):
|
||||
self.image.set_from_file(hic.ICON_INFO_DISPLAY_FILE)
|
||||
|
||||
class HobIndicator(gtk.DrawingArea):
|
||||
def __init__(self, count):
|
||||
gtk.DrawingArea.__init__(self)
|
||||
# Set no window for transparent background
|
||||
self.set_has_window(False)
|
||||
self.set_size_request(38,38)
|
||||
# We need to pass through button clicks
|
||||
self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
|
||||
class HobTabBar(gtk.DrawingArea):
|
||||
__gsignals__ = {
|
||||
"blank-area-changed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT,
|
||||
gobject.TYPE_INT,
|
||||
gobject.TYPE_INT,
|
||||
gobject.TYPE_INT,)),
|
||||
|
||||
self.connect('expose-event', self.expose)
|
||||
"tab-switched" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT,)),
|
||||
}
|
||||
|
||||
self.count = count
|
||||
self.color = HobColors.GRAY
|
||||
|
||||
def expose(self, widget, event):
|
||||
if self.count and self.count > 0:
|
||||
ctx = widget.window.cairo_create()
|
||||
|
||||
x, y, w, h = self.allocation
|
||||
|
||||
ctx.set_operator(cairo.OPERATOR_OVER)
|
||||
ctx.set_source_color(gtk.gdk.color_parse(self.color))
|
||||
ctx.translate(w/2, h/2)
|
||||
ctx.arc(x, y, min(w,h)/2 - 2, 0, 2*math.pi)
|
||||
ctx.fill_preserve()
|
||||
|
||||
layout = self.create_pango_layout(str(self.count))
|
||||
textw, texth = layout.get_pixel_size()
|
||||
x = (w/2)-(textw/2) + x
|
||||
y = (h/2) - (texth/2) + y
|
||||
ctx.move_to(x, y)
|
||||
self.window.draw_layout(self.style.light_gc[gtk.STATE_NORMAL], int(x), int(y), layout)
|
||||
|
||||
def set_count(self, count):
|
||||
self.count = count
|
||||
|
||||
def set_active(self, active):
|
||||
if active:
|
||||
self.color = HobColors.DEEP_RED
|
||||
else:
|
||||
self.color = HobColors.GRAY
|
||||
|
||||
class HobTabLabel(gtk.HBox):
|
||||
def __init__(self, text, count=0):
|
||||
gtk.HBox.__init__(self, False, 0)
|
||||
self.indicator = HobIndicator(count)
|
||||
self.indicator.show()
|
||||
self.pack_end(self.indicator, False, False)
|
||||
self.lbl = gtk.Label(text)
|
||||
self.lbl.set_alignment(0.0, 0.5)
|
||||
self.lbl.show()
|
||||
self.pack_end(self.lbl, True, True, 6)
|
||||
|
||||
def set_count(self, count):
|
||||
self.indicator.set_count(count)
|
||||
|
||||
def set_active(self, active=True):
|
||||
self.indicator.set_active(active)
|
||||
|
||||
class HobNotebook(gtk.Notebook):
|
||||
def __init__(self):
|
||||
gtk.Notebook.__init__(self)
|
||||
self.set_property('homogeneous', True)
|
||||
gtk.DrawingArea.__init__(self)
|
||||
self.children = []
|
||||
|
||||
self.pages = []
|
||||
self.tab_width = 140
|
||||
self.tab_height = 52
|
||||
self.tab_x = 10
|
||||
self.tab_y = 0
|
||||
|
||||
self.width = 500
|
||||
self.height = 53
|
||||
self.tab_w_ratio = 140 * 1.0/500
|
||||
self.tab_h_ratio = 52 * 1.0/53
|
||||
self.set_size_request(self.width, self.height)
|
||||
|
||||
self.current_child = None
|
||||
self.font = self.get_style().font_desc
|
||||
self.font.set_size(pango.SCALE * 13)
|
||||
self.update_children_text_layout_and_bg_color()
|
||||
|
||||
self.blank_rectangle = None
|
||||
self.tab_pressed = False
|
||||
|
||||
self.set_property('can-focus', True)
|
||||
self.set_events(gtk.gdk.EXPOSURE_MASK | gtk.gdk.POINTER_MOTION_MASK |
|
||||
gtk.gdk.BUTTON1_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK |
|
||||
gtk.gdk.BUTTON_RELEASE_MASK)
|
||||
|
||||
self.connect("expose-event", self.on_draw)
|
||||
self.connect("button-press-event", self.button_pressed_cb)
|
||||
self.connect("button-release-event", self.button_released_cb)
|
||||
self.connect("query-tooltip", self.query_tooltip_cb)
|
||||
self.show_all()
|
||||
|
||||
def button_released_cb(self, widget, event):
|
||||
self.tab_pressed = False
|
||||
self.queue_draw()
|
||||
|
||||
def button_pressed_cb(self, widget, event):
|
||||
if event.type == gtk.gdk._2BUTTON_PRESS:
|
||||
return
|
||||
|
||||
result = False
|
||||
if self.is_focus() or event.type == gtk.gdk.BUTTON_PRESS:
|
||||
x, y = event.get_coords()
|
||||
# check which tab be clicked
|
||||
for child in self.children:
|
||||
if (child["x"] < x) and (x < child["x"] + self.tab_width) \
|
||||
and (child["y"] < y) and (y < child["y"] + self.tab_height):
|
||||
self.current_child = child
|
||||
result = True
|
||||
self.grab_focus()
|
||||
break
|
||||
|
||||
# check the blank area is focus in or not
|
||||
if (self.blank_rectangle) and (self.blank_rectangle.x > 0) and (self.blank_rectangle.y > 0):
|
||||
if (self.blank_rectangle.x < x) and (x < self.blank_rectangle.x + self.blank_rectangle.width) \
|
||||
and (self.blank_rectangle.y < y) and (y < self.blank_rectangle.y + self.blank_rectangle.height):
|
||||
self.grab_focus()
|
||||
|
||||
if result == True:
|
||||
page = self.current_child["toggled_page"]
|
||||
self.emit("tab-switched", page)
|
||||
self.tab_pressed = True
|
||||
self.queue_draw()
|
||||
|
||||
def update_children_size(self):
|
||||
# calculate the size of tabs
|
||||
self.tab_width = int(self.width * self.tab_w_ratio)
|
||||
self.tab_height = int(self.height * self.tab_h_ratio)
|
||||
for i, child in enumerate(self.children):
|
||||
child["x"] = self.tab_x + i * self.tab_width
|
||||
child["y"] = self.tab_y
|
||||
|
||||
if self.blank_rectangle:
|
||||
self.resize_blank_rectangle()
|
||||
|
||||
def resize_blank_rectangle(self):
|
||||
width = self.width - self.tab_width * len(self.children) - self.tab_x
|
||||
x = self.tab_x + self.tab_width * len(self.children)
|
||||
hpadding = vpadding = 5
|
||||
self.blank_rectangle = self.set_blank_size(x + hpadding, self.tab_y + vpadding,
|
||||
width - 2 * hpadding, self.tab_height - 2 * vpadding)
|
||||
|
||||
def update_children_text_layout_and_bg_color(self):
|
||||
style = self.get_style().copy()
|
||||
color = style.base[gtk.STATE_NORMAL]
|
||||
for child in self.children:
|
||||
pangolayout = self.create_pango_layout(child["title"])
|
||||
pangolayout.set_font_description(self.font)
|
||||
child["title_layout"] = pangolayout
|
||||
child["r"] = color.red
|
||||
child["g"] = color.green
|
||||
child["b"] = color.blue
|
||||
|
||||
def append_tab_child(self, title, page, tooltip=""):
|
||||
num = len(self.children) + 1
|
||||
self.tab_width = self.tab_width * len(self.children) / num
|
||||
|
||||
i = 0
|
||||
for i, child in enumerate(self.children):
|
||||
child["x"] = self.tab_x + i * self.tab_width
|
||||
i += 1
|
||||
|
||||
x = self.tab_x + i * self.tab_width
|
||||
y = self.tab_y
|
||||
pangolayout = self.create_pango_layout(title)
|
||||
pangolayout.set_font_description(self.font)
|
||||
color = self.style.base[gtk.STATE_NORMAL]
|
||||
new_one = {
|
||||
"x" : x,
|
||||
"y" : y,
|
||||
"r" : color.red,
|
||||
"g" : color.green,
|
||||
"b" : color.blue,
|
||||
"title_layout" : pangolayout,
|
||||
"toggled_page" : page,
|
||||
"title" : title,
|
||||
"indicator_show" : False,
|
||||
"indicator_number" : 0,
|
||||
"tooltip_markup" : tooltip,
|
||||
}
|
||||
self.children.append(new_one)
|
||||
if tooltip and (not self.props.has_tooltip):
|
||||
self.props.has_tooltip = True
|
||||
# set the default current child
|
||||
if not self.current_child:
|
||||
self.current_child = new_one
|
||||
|
||||
def on_draw(self, widget, event):
|
||||
cr = widget.window.cairo_create()
|
||||
|
||||
self.width = self.allocation.width
|
||||
self.height = self.allocation.height
|
||||
|
||||
self.update_children_size()
|
||||
|
||||
self.draw_background(cr)
|
||||
self.draw_toggled_tab(cr)
|
||||
|
||||
for child in self.children:
|
||||
if child["indicator_show"] == True:
|
||||
self.draw_indicator(cr, child)
|
||||
|
||||
self.draw_tab_text(cr)
|
||||
|
||||
def draw_background(self, cr):
|
||||
style = self.get_style()
|
||||
|
||||
if self.is_focus():
|
||||
cr.set_source_color(style.base[gtk.STATE_SELECTED])
|
||||
else:
|
||||
cr.set_source_color(style.base[gtk.STATE_NORMAL])
|
||||
|
||||
y = 6
|
||||
h = self.height - 6 - 1
|
||||
gap = 1
|
||||
|
||||
w = self.children[0]["x"]
|
||||
cr.set_source_color(gtk.gdk.color_parse(HobColors.GRAY))
|
||||
cr.rectangle(0, y, w - gap, h) # start rectangle
|
||||
cr.fill()
|
||||
|
||||
cr.set_source_color(style.base[gtk.STATE_NORMAL])
|
||||
cr.rectangle(w - gap, y, w, h) #first gap
|
||||
cr.fill()
|
||||
|
||||
w = self.tab_width
|
||||
for child in self.children:
|
||||
x = child["x"]
|
||||
cr.set_source_color(gtk.gdk.color_parse(HobColors.GRAY))
|
||||
cr.rectangle(x, y, w - gap, h) # tab rectangle
|
||||
cr.fill()
|
||||
cr.set_source_color(style.base[gtk.STATE_NORMAL])
|
||||
cr.rectangle(x + w - gap, y, w, h) # gap
|
||||
cr.fill()
|
||||
|
||||
cr.set_source_color(gtk.gdk.color_parse(HobColors.GRAY))
|
||||
cr.rectangle(x + w, y, self.width - x - w, h) # last rectangle
|
||||
cr.fill()
|
||||
|
||||
def draw_tab_text(self, cr):
|
||||
style = self.get_style()
|
||||
|
||||
for child in self.children:
|
||||
pangolayout = child["title_layout"]
|
||||
if pangolayout:
|
||||
fontw, fonth = pangolayout.get_pixel_size()
|
||||
# center pos
|
||||
off_x = (self.tab_width - fontw) / 2
|
||||
off_y = (self.tab_height - fonth) / 2
|
||||
x = child["x"] + off_x
|
||||
y = child["y"] + off_y
|
||||
if not child == self.current_child:
|
||||
self.window.draw_layout(self.style.fg_gc[gtk.STATE_NORMAL], int(x), int(y), pangolayout, gtk.gdk.Color(HobColors.WHITE))
|
||||
else:
|
||||
self.window.draw_layout(self.style.fg_gc[gtk.STATE_NORMAL], int(x), int(y), pangolayout)
|
||||
|
||||
def draw_toggled_tab(self, cr):
|
||||
if not self.current_child:
|
||||
return
|
||||
x = self.current_child["x"]
|
||||
y = self.current_child["y"]
|
||||
width = self.tab_width
|
||||
height = self.tab_height
|
||||
style = self.get_style()
|
||||
color = style.base[gtk.STATE_NORMAL]
|
||||
|
||||
r = height / 10
|
||||
if self.tab_pressed == True:
|
||||
for xoff, yoff, c1, c2 in [(1, 0, HobColors.SLIGHT_DARK, HobColors.DARK), (2, 0, HobColors.GRAY, HobColors.LIGHT_GRAY)]:
|
||||
cr.set_source_color(gtk.gdk.color_parse(c1))
|
||||
cr.move_to(x + xoff, y + height + yoff)
|
||||
cr.line_to(x + xoff, r + yoff)
|
||||
cr.arc(x + r + xoff, y + r + yoff, r, math.pi, 1.5*math.pi)
|
||||
cr.move_to(x + r + xoff, y + yoff)
|
||||
cr.line_to(x + width - r + xoff, y + yoff)
|
||||
cr.arc(x + width - r + xoff, y + r + yoff, r, 1.5*math.pi, 2*math.pi)
|
||||
cr.stroke()
|
||||
cr.set_source_color(gtk.gdk.color_parse(c2))
|
||||
cr.move_to(x + width + xoff, r + yoff)
|
||||
cr.line_to(x + width + xoff, y + height + yoff)
|
||||
cr.line_to(x + xoff, y + height + yoff)
|
||||
cr.stroke()
|
||||
x = x + 2
|
||||
y = y + 2
|
||||
cr.set_source_rgba(color.red, color.green, color.blue, 1)
|
||||
cr.move_to(x + r, y)
|
||||
cr.line_to(x + width - r , y)
|
||||
cr.arc(x + width - r, y + r, r, 1.5*math.pi, 2*math.pi)
|
||||
cr.move_to(x + width, r)
|
||||
cr.line_to(x + width, y + height)
|
||||
cr.line_to(x, y + height)
|
||||
cr.line_to(x, r)
|
||||
cr.arc(x + r, y + r, r, math.pi, 1.5*math.pi)
|
||||
cr.fill()
|
||||
|
||||
def draw_indicator(self, cr, child):
|
||||
text = ("%d" % child["indicator_number"])
|
||||
layout = self.create_pango_layout(text)
|
||||
layout.set_font_description(self.font)
|
||||
textw, texth = layout.get_pixel_size()
|
||||
# draw the back round area
|
||||
tab_x = child["x"]
|
||||
tab_y = child["y"]
|
||||
dest_w = int(32 * self.tab_w_ratio)
|
||||
dest_h = int(32 * self.tab_h_ratio)
|
||||
if dest_h < self.tab_height:
|
||||
dest_w = dest_h
|
||||
# x position is offset(tab_width*3/4 - icon_width/2) + start_pos(tab_x)
|
||||
x = tab_x + self.tab_width * 3/4 - dest_w/2
|
||||
y = tab_y + self.tab_height/2 - dest_h/2
|
||||
|
||||
r = min(dest_w, dest_h)/2
|
||||
if not child == self.current_child:
|
||||
color = cr.set_source_color(gtk.gdk.color_parse(HobColors.DEEP_RED))
|
||||
else:
|
||||
color = cr.set_source_color(gtk.gdk.color_parse(HobColors.GRAY))
|
||||
# check round back area can contain the text or not
|
||||
back_round_can_contain_width = float(2 * r * 0.707)
|
||||
if float(textw) > back_round_can_contain_width:
|
||||
xoff = (textw - int(back_round_can_contain_width)) / 2
|
||||
cr.move_to(x + r - xoff, y + r + r)
|
||||
cr.arc((x + r - xoff), (y + r), r, 0.5*math.pi, 1.5*math.pi)
|
||||
cr.fill() # left half round
|
||||
cr.rectangle((x + r - xoff), y, 2 * xoff, 2 * r)
|
||||
cr.fill() # center rectangle
|
||||
cr.arc((x + r + xoff), (y + r), r, 1.5*math.pi, 0.5*math.pi)
|
||||
cr.fill() # right half round
|
||||
else:
|
||||
cr.arc((x + r), (y + r), r, 0, 2*math.pi)
|
||||
cr.fill()
|
||||
# draw the number text
|
||||
x = x + (dest_w/2)-(textw/2)
|
||||
y = y + (dest_h/2) - (texth/2)
|
||||
cr.move_to(x, y)
|
||||
self.window.draw_layout(self.style.fg_gc[gtk.STATE_NORMAL], int(x), int(y), layout, gtk.gdk.Color(HobColors.WHITE))
|
||||
|
||||
def show_indicator_icon(self, child, number):
|
||||
child["indicator_show"] = True
|
||||
child["indicator_number"] = number
|
||||
self.queue_draw()
|
||||
|
||||
def hide_indicator_icon(self, child):
|
||||
child["indicator_show"] = False
|
||||
self.queue_draw()
|
||||
|
||||
def set_blank_size(self, x, y, w, h):
|
||||
if not self.blank_rectangle or self.blank_rectangle.x != x or self.blank_rectangle.width != w:
|
||||
self.emit("blank-area-changed", x, y, w, h)
|
||||
|
||||
return gtk.gdk.Rectangle(x, y, w, h)
|
||||
|
||||
def query_tooltip_cb(self, widget, x, y, keyboardtip, tooltip):
|
||||
if keyboardtip or (not tooltip):
|
||||
return False
|
||||
# check which tab be clicked
|
||||
for child in self.children:
|
||||
if (child["x"] < x) and (x < child["x"] + self.tab_width) \
|
||||
and (child["y"] < y) and (y < child["y"] + self.tab_height):
|
||||
tooltip.set_markup(child["tooltip_markup"])
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
class HobNotebook(gtk.VBox):
|
||||
|
||||
def __init__(self):
|
||||
gtk.VBox.__init__(self, False, 0)
|
||||
|
||||
self.notebook = gtk.Notebook()
|
||||
self.notebook.set_property('homogeneous', True)
|
||||
self.notebook.set_property('show-tabs', False)
|
||||
|
||||
self.tabbar = HobTabBar()
|
||||
self.tabbar.connect("tab-switched", self.tab_switched_cb)
|
||||
self.notebook.connect("page-added", self.page_added_cb)
|
||||
self.notebook.connect("page-removed", self.page_removed_cb)
|
||||
|
||||
self.search = None
|
||||
self.search_name = ""
|
||||
|
||||
self.connect("switch-page", self.page_changed_cb)
|
||||
self.tb = gtk.Table(1, 100, False)
|
||||
self.hbox= gtk.HBox(False, 0)
|
||||
self.hbox.pack_start(self.tabbar, True, True)
|
||||
self.tb.attach(self.hbox, 0, 100, 0, 1)
|
||||
|
||||
self.pack_start(self.tb, False, False)
|
||||
self.pack_start(self.notebook)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def page_changed_cb(self, nb, page, page_num):
|
||||
for p, lbl in enumerate(self.pages):
|
||||
if p == page_num:
|
||||
lbl.set_active()
|
||||
else:
|
||||
lbl.set_active(False)
|
||||
|
||||
def append_page(self, child, tab_label, tab_tooltip=None):
|
||||
label = HobTabLabel(tab_label)
|
||||
if tab_tooltip:
|
||||
label.set_tooltip_text(tab_tooltip)
|
||||
label.set_active(False)
|
||||
self.pages.append(label)
|
||||
gtk.Notebook.append_page(self, child, label)
|
||||
def append_page(self, child, tab_label):
|
||||
self.notebook.set_current_page(self.notebook.append_page(child, tab_label))
|
||||
|
||||
def set_entry(self, name="Search:"):
|
||||
for child in self.tb.get_children():
|
||||
if child:
|
||||
self.tb.remove(child)
|
||||
|
||||
hbox_entry = gtk.HBox(False, 0)
|
||||
hbox_entry.show()
|
||||
|
||||
self.search = gtk.Entry()
|
||||
self.search_name = name
|
||||
style = self.search.get_style()
|
||||
@@ -497,20 +747,59 @@ class HobNotebook(gtk.Notebook):
|
||||
self.search.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLEAR)
|
||||
self.search.connect("icon-release", self.set_search_entry_clear_cb)
|
||||
self.search.show()
|
||||
self.align = gtk.Alignment(xalign=1.0, yalign=0.7)
|
||||
self.align.add(self.search)
|
||||
self.align.show()
|
||||
hbox_entry.pack_end(self.align, False, False)
|
||||
self.tabbar.resize_blank_rectangle()
|
||||
|
||||
self.tb.attach(hbox_entry, 75, 100, 0, 1, xpadding=5)
|
||||
self.tb.attach(self.hbox, 0, 100, 0, 1)
|
||||
|
||||
self.tabbar.connect("blank-area-changed", self.blank_area_resize_cb)
|
||||
self.search.connect("focus-in-event", self.set_search_entry_editable_cb)
|
||||
self.search.connect("focus-out-event", self.set_search_entry_reset_cb)
|
||||
self.set_action_widget(self.search, gtk.PACK_END)
|
||||
|
||||
self.tb.show()
|
||||
|
||||
def show_indicator_icon(self, title, number):
|
||||
for child in self.pages:
|
||||
if child.lbl.get_label() == title:
|
||||
child.set_count(number)
|
||||
for child in self.tabbar.children:
|
||||
if child["toggled_page"] == -1:
|
||||
continue
|
||||
if child["title"] == title:
|
||||
self.tabbar.show_indicator_icon(child, number)
|
||||
|
||||
def hide_indicator_icon(self, title):
|
||||
for child in self.pages:
|
||||
if child.lbl.get_label() == title:
|
||||
child.set_count(0)
|
||||
for child in self.tabbar.children:
|
||||
if child["toggled_page"] == -1:
|
||||
continue
|
||||
if child["title"] == title:
|
||||
self.tabbar.hide_indicator_icon(child)
|
||||
|
||||
def tab_switched_cb(self, widget, page):
|
||||
self.notebook.set_current_page(page)
|
||||
|
||||
def page_added_cb(self, notebook, notebook_child, page):
|
||||
if not notebook:
|
||||
return
|
||||
title = notebook.get_tab_label_text(notebook_child)
|
||||
label = notebook.get_tab_label(notebook_child)
|
||||
tooltip_markup = label.get_tooltip_markup()
|
||||
if not title:
|
||||
return
|
||||
for child in self.tabbar.children:
|
||||
if child["title"] == title:
|
||||
child["toggled_page"] = page
|
||||
return
|
||||
self.tabbar.append_tab_child(title, page, tooltip_markup)
|
||||
|
||||
def page_removed_cb(self, notebook, notebook_child, page, title=""):
|
||||
for child in self.tabbar.children:
|
||||
if child["title"] == title:
|
||||
child["toggled_page"] = -1
|
||||
|
||||
def blank_area_resize_cb(self, widget, request_x, request_y, request_width, request_height):
|
||||
self.search.set_size_request(request_width, request_height)
|
||||
|
||||
def set_search_entry_editable_cb(self, search, event):
|
||||
search.set_editable(True)
|
||||
@@ -530,14 +819,7 @@ class HobNotebook(gtk.Notebook):
|
||||
self.reset_entry(search)
|
||||
|
||||
def set_search_entry_clear_cb(self, search, icon_pos, event):
|
||||
if search.get_editable() == True:
|
||||
search.set_text("")
|
||||
|
||||
def set_page(self, title):
|
||||
for child in self.pages:
|
||||
if child.lbl.get_label() == title:
|
||||
child.grab_focus()
|
||||
self.set_current_page(self.page_num(child))
|
||||
self.reset_entry(search)
|
||||
|
||||
class HobWarpCellRendererText(gtk.CellRendererText):
|
||||
def __init__(self, col_number):
|
||||
@@ -802,17 +1084,11 @@ class HobCellRendererToggle(gtk.CellRendererToggle):
|
||||
gtk.CellRendererToggle.__init__(self)
|
||||
self.ctrl = HobCellRendererController(is_draw_row=True)
|
||||
self.ctrl.running_mode = self.ctrl.MODE_ONE_SHORT
|
||||
self.cell_attr = {"fadeout": False, "number_of_children": 0}
|
||||
self.cell_attr = {"fadeout": False}
|
||||
|
||||
def do_render(self, window, widget, background_area, cell_area, expose_area, flags):
|
||||
if (not self.ctrl) or (not widget):
|
||||
return
|
||||
|
||||
if flags & gtk.CELL_RENDERER_SELECTED:
|
||||
state = gtk.STATE_SELECTED
|
||||
else:
|
||||
state = gtk.STATE_NORMAL
|
||||
|
||||
if self.ctrl.is_active():
|
||||
path = widget.get_path_at_pos(cell_area.x + cell_area.width/2, cell_area.y + cell_area.height/2)
|
||||
# sometimes the parameters of cell_area will be a negative number,such as pull up down the scroll bar
|
||||
@@ -821,23 +1097,14 @@ class HobCellRendererToggle(gtk.CellRendererToggle):
|
||||
path = path[0]
|
||||
if path in self.ctrl.running_cell_areas:
|
||||
cr = window.cairo_create()
|
||||
color = widget.get_style().base[state]
|
||||
color = gtk.gdk.Color(HobColors.WHITE)
|
||||
|
||||
row_x, _, row_width, _ = widget.get_visible_rect()
|
||||
border_y = self.get_property("ypad")
|
||||
self.ctrl.on_draw_fadeinout_cb(cr, color, row_x, cell_area.y - border_y, row_width, \
|
||||
cell_area.height + border_y * 2, self.cell_attr["fadeout"])
|
||||
# draw number of a group
|
||||
if self.cell_attr["number_of_children"]:
|
||||
text = "%d pkg" % self.cell_attr["number_of_children"]
|
||||
pangolayout = widget.create_pango_layout(text)
|
||||
textw, texth = pangolayout.get_pixel_size()
|
||||
x = cell_area.x + (cell_area.width/2) - (textw/2)
|
||||
y = cell_area.y + (cell_area.height/2) - (texth/2)
|
||||
|
||||
widget.style.paint_layout(window, state, True, cell_area, widget, "checkbox", x, y, pangolayout)
|
||||
else:
|
||||
return gtk.CellRendererToggle.do_render(self, window, widget, background_area, cell_area, expose_area, flags)
|
||||
return gtk.CellRendererToggle.do_render(self, window, widget, background_area, cell_area, expose_area, flags)
|
||||
|
||||
'''delay: normally delay time is 1000ms
|
||||
cell_list: whilch cells need to be render
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
import gtk
|
||||
import glib
|
||||
import re
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hic, HobImageButton, HobInfoButton, HobAltButton, HobButton
|
||||
@@ -34,9 +33,6 @@ from bb.ui.crumbs.hobpages import HobPage
|
||||
#
|
||||
class ImageConfigurationPage (HobPage):
|
||||
|
||||
__dummy_machine__ = "--select a machine--"
|
||||
__dummy_image__ = "--select a base image--"
|
||||
|
||||
def __init__(self, builder):
|
||||
super(ImageConfigurationPage, self).__init__(builder, "Image configuration")
|
||||
|
||||
@@ -151,6 +147,7 @@ class ImageConfigurationPage (HobPage):
|
||||
self.machine_title_desc.set_markup(mark)
|
||||
|
||||
self.machine_combo = gtk.combo_box_new_text()
|
||||
self.machine_combo.set_wrap_width(1)
|
||||
self.machine_combo.connect("changed", self.machine_combo_changed_cb)
|
||||
|
||||
icon_file = hic.ICON_LAYERS_DISPLAY_FILE
|
||||
@@ -199,12 +196,11 @@ class ImageConfigurationPage (HobPage):
|
||||
self.image_title_desc.set_markup(mark)
|
||||
|
||||
self.image_combo = gtk.combo_box_new_text()
|
||||
self.image_combo.set_wrap_width(1)
|
||||
self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
|
||||
|
||||
self.image_desc = gtk.Label()
|
||||
self.image_desc.set_alignment(0.0, 0.5)
|
||||
self.image_desc.set_size_request(360, -1)
|
||||
self.image_desc.set_justify(gtk.JUSTIFY_LEFT)
|
||||
self.image_desc.set_line_wrap(True)
|
||||
|
||||
# button to view recipes
|
||||
@@ -263,15 +259,9 @@ class ImageConfigurationPage (HobPage):
|
||||
|
||||
def machine_combo_changed_cb(self, machine_combo):
|
||||
combo_item = machine_combo.get_active_text()
|
||||
if not combo_item or combo_item == self.__dummy_machine__:
|
||||
if not combo_item:
|
||||
return
|
||||
|
||||
# remove __dummy_machine__ item from the store list after first user selection
|
||||
# because it is no longer valid
|
||||
combo_store = machine_combo.get_model()
|
||||
if len(combo_store) and (combo_store[0][0] == self.__dummy_machine__):
|
||||
machine_combo.remove_text(0)
|
||||
|
||||
self.builder.configuration.curr_mach = combo_item
|
||||
if self.machine_combo_changed_by_manual:
|
||||
self.builder.configuration.clear_selection()
|
||||
@@ -282,13 +272,13 @@ class ImageConfigurationPage (HobPage):
|
||||
self.builder.populate_recipe_package_info_async()
|
||||
|
||||
def update_machine_combo(self):
|
||||
all_machines = [self.__dummy_machine__] + self.builder.parameters.all_machines
|
||||
all_machines = self.builder.parameters.all_machines
|
||||
|
||||
model = self.machine_combo.get_model()
|
||||
model.clear()
|
||||
for machine in all_machines:
|
||||
self.machine_combo.append_text(machine)
|
||||
self.machine_combo.set_active(0)
|
||||
self.machine_combo.set_active(-1)
|
||||
|
||||
def switch_machine_combo(self):
|
||||
self.machine_combo_changed_by_manual = False
|
||||
@@ -299,15 +289,10 @@ class ImageConfigurationPage (HobPage):
|
||||
self.machine_combo.set_active(active)
|
||||
return
|
||||
active += 1
|
||||
self.machine_combo.set_active(-1)
|
||||
|
||||
if model[0][0] != self.__dummy_machine__:
|
||||
self.machine_combo.insert_text(0, self.__dummy_machine__)
|
||||
|
||||
self.machine_combo.set_active(0)
|
||||
|
||||
def update_image_desc(self):
|
||||
def update_image_desc(self, selected_image):
|
||||
desc = ""
|
||||
selected_image = self.image_combo.get_active_text()
|
||||
if selected_image and selected_image in self.builder.recipe_model.pn_path.keys():
|
||||
image_path = self.builder.recipe_model.pn_path[selected_image]
|
||||
image_iter = self.builder.recipe_model.get_iter(image_path)
|
||||
@@ -324,15 +309,9 @@ class ImageConfigurationPage (HobPage):
|
||||
def image_combo_changed_cb(self, combo):
|
||||
self.builder.window_sensitive(False)
|
||||
selected_image = self.image_combo.get_active_text()
|
||||
if not selected_image or (selected_image == self.__dummy_image__):
|
||||
if not selected_image:
|
||||
return
|
||||
|
||||
# remove __dummy_image__ item from the store list after first user selection
|
||||
# because it is no longer valid
|
||||
combo_store = combo.get_model()
|
||||
if len(combo_store) and (combo_store[0][0] == self.__dummy_image__):
|
||||
combo.remove_text(0)
|
||||
|
||||
self.builder.customized = False
|
||||
|
||||
selected_recipes = []
|
||||
@@ -340,7 +319,7 @@ class ImageConfigurationPage (HobPage):
|
||||
image_path = self.builder.recipe_model.pn_path[selected_image]
|
||||
image_iter = self.builder.recipe_model.get_iter(image_path)
|
||||
selected_packages = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_INSTALL).split()
|
||||
self.update_image_desc()
|
||||
self.update_image_desc(selected_image)
|
||||
|
||||
self.builder.recipe_model.reset()
|
||||
self.builder.package_model.reset()
|
||||
@@ -363,61 +342,32 @@ class ImageConfigurationPage (HobPage):
|
||||
# populate image combo
|
||||
filter = {RecipeListModel.COL_TYPE : ['image']}
|
||||
image_model = recipe_model.tree_model(filter)
|
||||
active = 0
|
||||
cnt = 1
|
||||
|
||||
white_pattern = []
|
||||
if self.builder.parameters.image_white_pattern:
|
||||
for i in self.builder.parameters.image_white_pattern.split():
|
||||
white_pattern.append(re.compile(i))
|
||||
|
||||
black_pattern = []
|
||||
if self.builder.parameters.image_black_pattern:
|
||||
for i in self.builder.parameters.image_black_pattern.split():
|
||||
black_pattern.append(re.compile(i))
|
||||
active = -1
|
||||
cnt = 0
|
||||
|
||||
it = image_model.get_iter_first()
|
||||
self._image_combo_disconnect_signal()
|
||||
model = self.image_combo.get_model()
|
||||
model.clear()
|
||||
# Set a indicator text to combo store when first open
|
||||
self.image_combo.append_text(self.__dummy_image__)
|
||||
# append and set active
|
||||
while it:
|
||||
path = image_model.get_path(it)
|
||||
it = image_model.iter_next(it)
|
||||
image_name = image_model[path][recipe_model.COL_NAME]
|
||||
if image_name == self.builder.recipe_model.__custom_image__:
|
||||
if image_name == self.builder.recipe_model.__dummy_image__:
|
||||
continue
|
||||
|
||||
if black_pattern:
|
||||
allow = True
|
||||
for pattern in black_pattern:
|
||||
if pattern.search(image_name):
|
||||
allow = False
|
||||
break
|
||||
elif white_pattern:
|
||||
allow = False
|
||||
for pattern in white_pattern:
|
||||
if pattern.search(image_name):
|
||||
allow = True
|
||||
break
|
||||
else:
|
||||
allow = True
|
||||
|
||||
if allow:
|
||||
self.image_combo.append_text(image_name)
|
||||
if image_name == selected_image:
|
||||
active = cnt
|
||||
cnt = cnt + 1
|
||||
|
||||
self.image_combo.append_text(self.builder.recipe_model.__custom_image__)
|
||||
if selected_image == self.builder.recipe_model.__custom_image__:
|
||||
self.image_combo.append_text(image_name)
|
||||
if image_name == selected_image:
|
||||
active = cnt
|
||||
cnt = cnt + 1
|
||||
self.image_combo.append_text(self.builder.recipe_model.__dummy_image__)
|
||||
if selected_image == self.builder.recipe_model.__dummy_image__:
|
||||
active = cnt
|
||||
|
||||
self.image_combo.set_active(-1)
|
||||
self.image_combo.set_active(active)
|
||||
|
||||
if active != 0:
|
||||
if active != -1:
|
||||
self.show_baseimg_selected()
|
||||
|
||||
self._image_combo_connect_signal()
|
||||
|
||||
@@ -25,15 +25,34 @@ import gtk
|
||||
from bb.ui.crumbs.hobcolor import HobColors
|
||||
from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
import subprocess
|
||||
from bb.ui.crumbs.hig import CrumbsDialog
|
||||
|
||||
#
|
||||
# ImageDetailsPage
|
||||
#
|
||||
class ImageDetailsPage (HobPage):
|
||||
|
||||
__columns__ = [{
|
||||
'col_name' : 'Image name',
|
||||
'col_id' : 0,
|
||||
'col_style': 'text',
|
||||
'col_min' : 500,
|
||||
'col_max' : 500
|
||||
}, {
|
||||
'col_name' : 'Image size',
|
||||
'col_id' : 1,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 100
|
||||
}, {
|
||||
'col_name' : 'Select',
|
||||
'col_id' : 2,
|
||||
'col_style': 'radio toggle',
|
||||
'col_min' : 100,
|
||||
'col_max' : 100
|
||||
}]
|
||||
|
||||
class DetailBox (gtk.EventBox):
|
||||
def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, button2=None, color = HobColors.LIGHT_GRAY):
|
||||
def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, color = HobColors.LIGHT_GRAY):
|
||||
gtk.EventBox.__init__(self)
|
||||
|
||||
# set color
|
||||
@@ -42,41 +61,33 @@ class ImageDetailsPage (HobPage):
|
||||
self.set_style(style)
|
||||
|
||||
self.hbox = gtk.HBox()
|
||||
self.hbox.set_border_width(10)
|
||||
self.hbox.set_border_width(15)
|
||||
self.add(self.hbox)
|
||||
|
||||
total_rows = 0
|
||||
if widget:
|
||||
total_rows = 10
|
||||
if varlist and vallist:
|
||||
row = 1
|
||||
elif varlist and vallist:
|
||||
# pack the icon and the text on the left
|
||||
total_rows += len(varlist)
|
||||
self.table = gtk.Table(total_rows, 20, True)
|
||||
self.table.set_row_spacings(6)
|
||||
row = len(varlist)
|
||||
self.table = gtk.Table(row, 20, True)
|
||||
self.table.set_size_request(100, -1)
|
||||
self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)
|
||||
|
||||
colid = 0
|
||||
rowid = 0
|
||||
self.line_widgets = {}
|
||||
if icon:
|
||||
self.table.attach(icon, colid, colid + 2, 0, 1)
|
||||
colid = colid + 2
|
||||
if widget:
|
||||
self.table.attach(widget, colid, 20, 0, 10)
|
||||
rowid = 10
|
||||
if varlist and vallist:
|
||||
for row in range(rowid, total_rows):
|
||||
index = row - rowid
|
||||
self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
|
||||
self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
|
||||
self.table.attach(widget, colid, 20, 0, 1)
|
||||
elif varlist and vallist:
|
||||
for line in range(0, row):
|
||||
self.line_widgets[varlist[line]] = self.text2label(varlist[line], vallist[line])
|
||||
self.table.attach(self.line_widgets[varlist[line]], colid, 20, line, line + 1)
|
||||
|
||||
# pack the button on the right
|
||||
if button:
|
||||
self.bbox = gtk.VBox()
|
||||
self.bbox.pack_start(button, expand=True, fill=True)
|
||||
if button2:
|
||||
self.bbox.pack_start(button2, expand=True, fill=True)
|
||||
self.hbox.pack_end(self.bbox, expand=False, fill=False)
|
||||
self.hbox.pack_end(button, expand=False, fill=False)
|
||||
|
||||
def update_line_widgets(self, variable, value):
|
||||
if len(self.line_widgets) == 0:
|
||||
@@ -85,23 +96,9 @@ class ImageDetailsPage (HobPage):
|
||||
return
|
||||
self.line_widgets[variable].set_markup(self.format_line(variable, value))
|
||||
|
||||
def wrap_line(self, inputs):
|
||||
# wrap the long text of inputs
|
||||
wrap_width_chars = 75
|
||||
outputs = ""
|
||||
tmps = inputs
|
||||
less_chars = len(inputs)
|
||||
while (less_chars - wrap_width_chars) > 0:
|
||||
less_chars -= wrap_width_chars
|
||||
outputs += tmps[:wrap_width_chars] + "\n "
|
||||
tmps = inputs[less_chars:]
|
||||
outputs += tmps
|
||||
return outputs
|
||||
|
||||
def format_line(self, variable, value):
|
||||
wraped_value = self.wrap_line(value)
|
||||
markup = "<span weight=\'bold\'>%s</span>" % variable
|
||||
markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
|
||||
markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % value
|
||||
return markup
|
||||
|
||||
def text2label(self, variable, value):
|
||||
@@ -115,7 +112,7 @@ class ImageDetailsPage (HobPage):
|
||||
def __init__(self, builder):
|
||||
super(ImageDetailsPage, self).__init__(builder, "Image details")
|
||||
|
||||
self.image_store = []
|
||||
self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
|
||||
self.button_ids = {}
|
||||
self.details_bottom_buttons = gtk.HBox(False, 6)
|
||||
self.create_visual_elements()
|
||||
@@ -160,30 +157,27 @@ class ImageDetailsPage (HobPage):
|
||||
self.details_bottom_buttons.remove(child)
|
||||
|
||||
def show_page(self, step):
|
||||
self.build_succeeded = (step == self.builder.IMAGE_GENERATED)
|
||||
build_succeeded = (step == self.builder.IMAGE_GENERATED)
|
||||
image_addr = self.builder.parameters.image_addr
|
||||
image_names = self.builder.parameters.image_names
|
||||
if self.build_succeeded:
|
||||
if build_succeeded:
|
||||
machine = self.builder.configuration.curr_mach
|
||||
base_image = self.builder.recipe_model.get_selected_image()
|
||||
layers = self.builder.configuration.layers
|
||||
pkg_num = "%s" % len(self.builder.package_model.get_selected_packages())
|
||||
log_file = self.builder.current_logfile
|
||||
else:
|
||||
pkg_num = "N/A"
|
||||
log_file = None
|
||||
|
||||
# remove
|
||||
for button_id, button in self.button_ids.items():
|
||||
button.disconnect(button_id)
|
||||
self._remove_all_widget()
|
||||
|
||||
# repack
|
||||
self.pack_start(self.details_top_buttons, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
self.build_result = None
|
||||
if self.build_succeeded:
|
||||
if build_succeeded:
|
||||
# building is the previous step
|
||||
icon = gtk.Image()
|
||||
pixmap_path = hic.ICON_INDI_CONFIRM_FILE
|
||||
@@ -196,89 +190,45 @@ class ImageDetailsPage (HobPage):
|
||||
self.box_group_area.pack_start(self.build_result, expand=False, fill=False)
|
||||
|
||||
# create the buttons at the bottom first because the buttons are used in apply_button_per_image()
|
||||
if self.build_succeeded:
|
||||
if build_succeeded:
|
||||
self.buttonlist = ["Build new image", "Save as template", "Run image", "Deploy image"]
|
||||
else: # get to this page from "My images"
|
||||
self.buttonlist = ["Build new image", "Run image", "Deploy image"]
|
||||
|
||||
# Name
|
||||
self.image_store = []
|
||||
self.toggled_image = ""
|
||||
self.image_store.clear()
|
||||
default_toggled = False
|
||||
default_image_size = 0
|
||||
self.num_toggled = 0
|
||||
i = 0
|
||||
for image_name in image_names:
|
||||
image_size = HobPage._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size)
|
||||
|
||||
image_attr = ("run" if (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) else \
|
||||
("deploy" if self.test_deployable(image_name) else ""))
|
||||
is_toggled = (image_attr != "")
|
||||
|
||||
if not self.toggled_image:
|
||||
if not default_toggled:
|
||||
default_toggled = (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) \
|
||||
or self.test_deployable(image_name)
|
||||
if i == (len(image_names) - 1):
|
||||
is_toggled = True
|
||||
if is_toggled:
|
||||
default_toggled = True
|
||||
self.image_store.set(self.image_store.append(), 0, image_name, 1, image_size, 2, default_toggled)
|
||||
if default_toggled:
|
||||
default_image_size = image_size
|
||||
self.toggled_image = image_name
|
||||
|
||||
split_stuff = image_name.split('.')
|
||||
if "rootfs" in split_stuff:
|
||||
image_type = image_name[(len(split_stuff[0]) + len(".rootfs") + 1):]
|
||||
self.create_bottom_buttons(self.buttonlist, image_name)
|
||||
else:
|
||||
image_type = image_name[(len(split_stuff[0]) + 1):]
|
||||
|
||||
self.image_store.append({'name': image_name,
|
||||
'type': image_type,
|
||||
'size': image_size,
|
||||
'is_toggled': is_toggled,
|
||||
'action_attr': image_attr,})
|
||||
|
||||
self.image_store.set(self.image_store.append(), 0, image_name, 1, image_size, 2, False)
|
||||
i = i + 1
|
||||
self.num_toggled += is_toggled
|
||||
|
||||
is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image)
|
||||
|
||||
# Generated image files info
|
||||
varlist = ["Name: ", "FileCreated: ", "Directory: "]
|
||||
vallist = []
|
||||
|
||||
vallist.append(image_name.split('.')[0])
|
||||
vallist.append(', '.join(fileitem['type'] for fileitem in self.image_store))
|
||||
vallist.append(image_addr)
|
||||
|
||||
image_table = HobViewTable(self.__columns__)
|
||||
image_table.set_model(self.image_store)
|
||||
image_table.connect("toggled", self.toggled_cb)
|
||||
view_files_button = HobAltButton("View files")
|
||||
view_files_button.connect("clicked", self.view_files_clicked_cb, image_addr)
|
||||
view_files_button.set_tooltip_text("Open the directory containing the image files")
|
||||
view_log_button = None
|
||||
if log_file:
|
||||
view_log_button = HobAltButton("View log")
|
||||
view_log_button.connect("clicked", self.view_log_clicked_cb, log_file)
|
||||
view_log_button.set_tooltip_text("Open the building log files")
|
||||
self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=view_log_button)
|
||||
self.box_group_area.pack_start(self.image_detail, expand=False, fill=True)
|
||||
|
||||
# The default kernel box for the qemu images
|
||||
self.sel_kernel = ""
|
||||
self.kernel_detail = None
|
||||
if 'qemu' in image_name:
|
||||
self.sel_kernel = self.get_kernel_file_name()
|
||||
|
||||
varlist = ["Kernel: "]
|
||||
vallist = []
|
||||
vallist.append(self.sel_kernel)
|
||||
|
||||
change_kernel_button = HobAltButton("Change")
|
||||
change_kernel_button.connect("clicked", self.change_kernel_cb)
|
||||
change_kernel_button.set_tooltip_text("Change qemu kernel file")
|
||||
self.kernel_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=change_kernel_button)
|
||||
self.box_group_area.pack_start(self.kernel_detail, expand=False, fill=False)
|
||||
self.image_detail = self.DetailBox(widget=image_table, button=view_files_button)
|
||||
self.box_group_area.pack_start(self.image_detail, expand=True, fill=True)
|
||||
|
||||
# Machine, Base image and Layers
|
||||
layer_num_limit = 15
|
||||
varlist = ["Machine: ", "Base image: ", "Layers: "]
|
||||
vallist = []
|
||||
self.setting_detail = None
|
||||
if self.build_succeeded:
|
||||
if build_succeeded:
|
||||
vallist.append(machine)
|
||||
vallist.append(base_image)
|
||||
i = 0
|
||||
@@ -302,14 +252,14 @@ class ImageDetailsPage (HobPage):
|
||||
edit_config_button.set_tooltip_text("Edit machine, base image and recipes")
|
||||
edit_config_button.connect("clicked", self.edit_config_button_clicked_cb)
|
||||
self.setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_config_button)
|
||||
self.box_group_area.pack_start(self.setting_detail, expand=True, fill=True)
|
||||
self.box_group_area.pack_start(self.setting_detail, expand=False, fill=False)
|
||||
|
||||
# Packages included, and Total image size
|
||||
varlist = ["Packages included: ", "Total image size: "]
|
||||
vallist = []
|
||||
vallist.append(pkg_num)
|
||||
vallist.append(default_image_size)
|
||||
if self.build_succeeded:
|
||||
if build_succeeded:
|
||||
edit_packages_button = HobAltButton("Edit packages")
|
||||
edit_packages_button.set_tooltip_text("Edit the packages included in your image")
|
||||
edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb)
|
||||
@@ -319,23 +269,12 @@ class ImageDetailsPage (HobPage):
|
||||
self.box_group_area.pack_start(self.package_detail, expand=False, fill=False)
|
||||
|
||||
# pack the buttons at the bottom, at this time they are already created.
|
||||
if self.build_succeeded:
|
||||
self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
|
||||
else: # for "My images" page
|
||||
self.details_separator = gtk.HSeparator()
|
||||
self.box_group_area.pack_start(self.details_separator, expand=False, fill=False)
|
||||
self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False)
|
||||
self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
|
||||
|
||||
self.show_all()
|
||||
if self.kernel_detail and (not is_runnable):
|
||||
self.kernel_detail.hide()
|
||||
|
||||
def view_files_clicked_cb(self, button, image_addr):
|
||||
subprocess.call("xdg-open /%s" % image_addr, shell=True)
|
||||
|
||||
def view_log_clicked_cb(self, button, log_file):
|
||||
if log_file:
|
||||
os.system("xdg-open /%s" % log_file)
|
||||
os.system("xdg-open /%s" % image_addr)
|
||||
|
||||
def refresh_package_detail_box(self, image_size):
|
||||
self.package_detail.update_line_widgets("Total image size: ", image_size)
|
||||
@@ -364,109 +303,43 @@ class ImageDetailsPage (HobPage):
|
||||
break
|
||||
return deployable
|
||||
|
||||
def get_kernel_file_name(self, kernel_addr=""):
|
||||
kernel_name = ""
|
||||
|
||||
if not kernel_addr:
|
||||
kernel_addr = self.builder.parameters.image_addr
|
||||
|
||||
files = [f for f in os.listdir(kernel_addr) if f[0] <> '.']
|
||||
for check_file in files:
|
||||
if check_file.endswith(".bin"):
|
||||
name_splits = check_file.split(".")[0]
|
||||
if self.builder.parameters.kernel_image_type in name_splits.split("-"):
|
||||
kernel_name = check_file
|
||||
break
|
||||
|
||||
return kernel_name
|
||||
|
||||
def show_builded_images_dialog(self, widget, primary_action=""):
|
||||
title = primary_action if primary_action else "Your builded images"
|
||||
dialog = CrumbsDialog(title, self.builder,
|
||||
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
dialog.set_border_width(12)
|
||||
|
||||
label = gtk.Label()
|
||||
label.set_use_markup(True)
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action)
|
||||
dialog.vbox.pack_start(label, expand=False, fill=False)
|
||||
|
||||
# filter created images as action attribution (deploy or run)
|
||||
action_attr = ""
|
||||
action_images = []
|
||||
for fileitem in self.image_store:
|
||||
action_attr = fileitem['action_attr']
|
||||
if (action_attr == 'run' and primary_action == "Run image") \
|
||||
or (action_attr == 'deploy' and primary_action == "Deploy image"):
|
||||
action_images.append(fileitem)
|
||||
|
||||
# pack the corresponding 'runnable' or 'deploy' radio_buttons, if there has no more than one file.
|
||||
# assume that there does not both have 'deploy' and 'runnable' files in the same building result
|
||||
# in possible as design.
|
||||
curr_row = 0
|
||||
rows = (len(action_images)) if len(action_images) < 10 else 10
|
||||
table = gtk.Table(rows, 10, True)
|
||||
table.set_row_spacings(6)
|
||||
table.set_col_spacing(0, 12)
|
||||
table.set_col_spacing(5, 12)
|
||||
|
||||
sel_parent_btn = None
|
||||
for fileitem in action_images:
|
||||
sel_btn = gtk.RadioButton(sel_parent_btn, fileitem['type'])
|
||||
sel_parent_btn = sel_btn if not sel_parent_btn else sel_parent_btn
|
||||
sel_btn.set_active(fileitem['is_toggled'])
|
||||
sel_btn.connect('toggled', self.table_selected_cb, fileitem)
|
||||
if curr_row < 10:
|
||||
table.attach(sel_btn, 2, 5, curr_row, curr_row + 1)
|
||||
else:
|
||||
table.attach(sel_btn, 7, 10, curr_row - 10, curr_row - 9)
|
||||
curr_row += 1
|
||||
|
||||
dialog.vbox.pack_start(table, expand=False, fill=False, padding = 6)
|
||||
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
|
||||
HobAltButton.style_button(button)
|
||||
|
||||
if primary_action:
|
||||
button = dialog.add_button(primary_action, gtk.RESPONSE_YES)
|
||||
HobButton.style_button(button)
|
||||
|
||||
dialog.show_all()
|
||||
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
if response != gtk.RESPONSE_YES:
|
||||
def toggled_cb(self, table, cell, path, columnid, tree):
|
||||
model = tree.get_model()
|
||||
if not model:
|
||||
return
|
||||
iter = model.get_iter_first()
|
||||
while iter:
|
||||
rowpath = model.get_path(iter)
|
||||
model[rowpath][columnid] = False
|
||||
iter = model.iter_next(iter)
|
||||
|
||||
for fileitem in self.image_store:
|
||||
if fileitem['is_toggled']:
|
||||
if fileitem['action_attr'] == 'run':
|
||||
self.builder.runqemu_image(fileitem['name'], self.sel_kernel)
|
||||
elif fileitem['action_attr'] == 'deploy':
|
||||
self.builder.deploy_image(fileitem['name'])
|
||||
model[path][columnid] = True
|
||||
self.refresh_package_detail_box(model[path][1])
|
||||
|
||||
def table_selected_cb(self, tbutton, image):
|
||||
image['is_toggled'] = tbutton.get_active()
|
||||
if image['is_toggled']:
|
||||
self.toggled_image = image['name']
|
||||
image_name = model[path][0]
|
||||
|
||||
def change_kernel_cb(self, widget):
|
||||
kernel_path = self.builder.show_load_kernel_dialog()
|
||||
if kernel_path and self.kernel_detail:
|
||||
import os.path
|
||||
self.sel_kernel = os.path.basename(kernel_path)
|
||||
markup = self.kernel_detail.format_line("Kernel: ", self.sel_kernel)
|
||||
label = ((self.kernel_detail.get_children()[0]).get_children()[0]).get_children()[0]
|
||||
label.set_markup(markup)
|
||||
# remove
|
||||
for button_id, button in self.button_ids.items():
|
||||
button.disconnect(button_id)
|
||||
self._remove_all_widget()
|
||||
# repack
|
||||
self.pack_start(self.details_top_buttons, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
if self.build_result:
|
||||
self.box_group_area.pack_start(self.build_result, expand=False, fill=False)
|
||||
self.box_group_area.pack_start(self.image_detail, expand=True, fill=True)
|
||||
if self.setting_detail:
|
||||
self.box_group_area.pack_start(self.setting_detail, expand=False, fill=False)
|
||||
self.box_group_area.pack_start(self.package_detail, expand=False, fill=False)
|
||||
self.create_bottom_buttons(self.buttonlist, image_name)
|
||||
self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
|
||||
self.show_all()
|
||||
|
||||
def create_bottom_buttons(self, buttonlist, image_name):
|
||||
# Create the buttons at the bottom
|
||||
created = False
|
||||
packed = False
|
||||
self.button_ids = {}
|
||||
is_runnable = False
|
||||
|
||||
# create button "Deploy image"
|
||||
name = "Deploy image"
|
||||
@@ -501,7 +374,15 @@ class ImageDetailsPage (HobPage):
|
||||
self.button_ids[button_id] = run_button
|
||||
self.details_bottom_buttons.pack_end(run_button, expand=False, fill=False)
|
||||
created = True
|
||||
is_runnable = True
|
||||
|
||||
if not packed:
|
||||
box = gtk.HBox(False, 6)
|
||||
box.show()
|
||||
subbox = gtk.HBox(False, 0)
|
||||
subbox.set_size_request(205, 49)
|
||||
subbox.show()
|
||||
box.add(subbox)
|
||||
self.details_bottom_buttons.pack_end(box, False, False)
|
||||
|
||||
name = "Save as template"
|
||||
if name in buttonlist:
|
||||
@@ -510,13 +391,8 @@ class ImageDetailsPage (HobPage):
|
||||
label = gtk.Label(" or ")
|
||||
self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Save as template"
|
||||
save_button = HobAltButton("Save as template")
|
||||
else:
|
||||
save_button = HobButton("Save as template")
|
||||
save_button.set_size_request(205, 49)
|
||||
save_button.set_flags(gtk.CAN_DEFAULT)
|
||||
packed = True
|
||||
# create button "Save as template"
|
||||
save_button = HobAltButton("Save as template")
|
||||
save_button.set_tooltip_text("Save the image configuration for reuse")
|
||||
button_id = save_button.connect("clicked", self.save_button_clicked_cb)
|
||||
self.button_ids[button_id] = save_button
|
||||
@@ -526,39 +402,34 @@ class ImageDetailsPage (HobPage):
|
||||
name = "Build new image"
|
||||
if name in buttonlist:
|
||||
# create button "Build new image"
|
||||
if packed:
|
||||
build_new_button = HobAltButton("Build new image")
|
||||
else:
|
||||
build_new_button = HobButton("Build new image")
|
||||
build_new_button.set_flags(gtk.CAN_DEFAULT)
|
||||
build_new_button.set_size_request(205, 49)
|
||||
self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False)
|
||||
build_new_button = HobAltButton("Build new image")
|
||||
build_new_button.set_tooltip_text("Create a new image from scratch")
|
||||
button_id = build_new_button.connect("clicked", self.build_new_button_clicked_cb)
|
||||
self.button_ids[button_id] = build_new_button
|
||||
self.details_bottom_buttons.pack_start(build_new_button, expand=False, fill=False)
|
||||
|
||||
return is_runnable
|
||||
def _get_selected_image(self):
|
||||
image_name = ""
|
||||
iter = self.image_store.get_iter_first()
|
||||
while iter:
|
||||
path = self.image_store.get_path(iter)
|
||||
if self.image_store[path][2]:
|
||||
image_name = self.image_store[path][0]
|
||||
break
|
||||
iter = self.image_store.iter_next(iter)
|
||||
|
||||
return image_name
|
||||
|
||||
def save_button_clicked_cb(self, button):
|
||||
self.builder.show_save_template_dialog()
|
||||
|
||||
def deploy_button_clicked_cb(self, button):
|
||||
if self.toggled_image:
|
||||
if self.num_toggled > 1:
|
||||
self.set_sensitive(False)
|
||||
self.show_builded_images_dialog(None, "Deploy image")
|
||||
self.set_sensitive(True)
|
||||
else:
|
||||
self.builder.deploy_image(self.toggled_image)
|
||||
image_name = self._get_selected_image()
|
||||
self.builder.deploy_image(image_name)
|
||||
|
||||
def run_button_clicked_cb(self, button):
|
||||
if self.toggled_image:
|
||||
if self.num_toggled > 1:
|
||||
self.set_sensitive(False)
|
||||
self.show_builded_images_dialog(None, "Run image")
|
||||
self.set_sensitive(True)
|
||||
else:
|
||||
self.builder.runqemu_image(self.toggled_image, self.sel_kernel)
|
||||
image_name = self._get_selected_image()
|
||||
self.builder.runqemu_image(image_name)
|
||||
|
||||
def build_new_button_clicked_cb(self, button):
|
||||
self.builder.initiate_new_build_async()
|
||||
|
||||
@@ -39,7 +39,6 @@ class PackageSelectionPage (HobPage):
|
||||
'columns' : [{
|
||||
'col_name' : 'Package name',
|
||||
'col_id' : PackageListModel.COL_NAME,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
@@ -47,7 +46,6 @@ class PackageSelectionPage (HobPage):
|
||||
}, {
|
||||
'col_name' : 'Brought in by',
|
||||
'col_id' : PackageListModel.COL_BINB,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'binb',
|
||||
'col_min' : 100,
|
||||
'col_max' : 350,
|
||||
@@ -55,7 +53,6 @@ class PackageSelectionPage (HobPage):
|
||||
}, {
|
||||
'col_name' : 'Size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
@@ -63,9 +60,7 @@ class PackageSelectionPage (HobPage):
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : PackageListModel.COL_INC,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'check toggle',
|
||||
'col_group': 'tree store group',
|
||||
'col_min' : 100,
|
||||
'col_max' : 100
|
||||
}]
|
||||
@@ -75,7 +70,6 @@ class PackageSelectionPage (HobPage):
|
||||
'columns' : [{
|
||||
'col_name' : 'Package name',
|
||||
'col_id' : PackageListModel.COL_NAME,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
@@ -83,7 +77,6 @@ class PackageSelectionPage (HobPage):
|
||||
}, {
|
||||
'col_name' : 'Size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 500,
|
||||
@@ -92,7 +85,6 @@ class PackageSelectionPage (HobPage):
|
||||
'col_name' : 'Included',
|
||||
'col_id' : PackageListModel.COL_INC,
|
||||
'col_style': 'check toggle',
|
||||
'col_group': 'tree store group',
|
||||
'col_min' : 100,
|
||||
'col_max' : 100
|
||||
}]
|
||||
@@ -109,16 +101,13 @@ class PackageSelectionPage (HobPage):
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def included_clicked_cb(self, button):
|
||||
self.ins.set_current_page(0)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.label = gtk.Label("Packages included: 0\nSelected packages size: 0 MB")
|
||||
self.eventbox = self.add_onto_top_bar(self.label, 73)
|
||||
self.pack_start(self.eventbox, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
# set visible members
|
||||
# set visiable members
|
||||
self.ins = HobNotebook()
|
||||
self.tables = [] # we need to modify table when the dialog is shown
|
||||
# append the tab
|
||||
@@ -128,11 +117,11 @@ class PackageSelectionPage (HobPage):
|
||||
filter = page['filter']
|
||||
tab.set_model(self.package_model.tree_model(filter))
|
||||
tab.connect("toggled", self.table_toggled_cb, page['name'])
|
||||
tab.connect_group_selection(self.table_selected_cb)
|
||||
if page['name'] == "Included":
|
||||
tab.connect("button-release-event", self.button_click_cb)
|
||||
tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include)
|
||||
self.ins.append_page(tab, page['name'])
|
||||
label = gtk.Label(page['name'])
|
||||
self.ins.append_page(tab, label)
|
||||
self.tables.append(tab)
|
||||
|
||||
self.ins.set_entry("Search packages:")
|
||||
@@ -143,8 +132,8 @@ class PackageSelectionPage (HobPage):
|
||||
# add all into the dialog
|
||||
self.box_group_area.pack_start(self.ins, expand=True, fill=True)
|
||||
|
||||
self.button_box = gtk.HBox(False, 6)
|
||||
self.box_group_area.pack_start(self.button_box, expand=False, fill=False)
|
||||
button_box = gtk.HBox(False, 6)
|
||||
self.box_group_area.pack_start(button_box, expand=False, fill=False)
|
||||
|
||||
self.build_image_button = HobButton('Build image')
|
||||
self.build_image_button.set_size_request(205, 49)
|
||||
@@ -152,11 +141,11 @@ class PackageSelectionPage (HobPage):
|
||||
self.build_image_button.set_flags(gtk.CAN_DEFAULT)
|
||||
self.build_image_button.grab_default()
|
||||
self.build_image_button.connect("clicked", self.build_image_clicked_cb)
|
||||
self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
|
||||
button_box.pack_end(self.build_image_button, expand=False, fill=False)
|
||||
|
||||
self.back_button = HobAltButton("<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
self.button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
|
||||
def button_click_cb(self, widget, event):
|
||||
path, col = widget.table_tree.get_cursor()
|
||||
@@ -166,25 +155,6 @@ class PackageSelectionPage (HobPage):
|
||||
if binb:
|
||||
self.builder.show_binb_dialog(binb)
|
||||
|
||||
def view_log_clicked_cb(self, button, log_file):
|
||||
if log_file:
|
||||
os.system("xdg-open /%s" % log_file)
|
||||
|
||||
def show_page(self, log_file):
|
||||
children = self.button_box.get_children() or []
|
||||
for child in children:
|
||||
self.button_box.remove(child)
|
||||
# re-packed the buttons as request, add the 'view log' button if build success
|
||||
self.button_box.pack_start(self.back_button, expand=False, fill=False)
|
||||
self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
|
||||
if log_file:
|
||||
view_log_button = HobAltButton("View log")
|
||||
view_log_button.connect("clicked", self.view_log_clicked_cb, log_file)
|
||||
view_log_button.set_tooltip_text("Open the building log files")
|
||||
self.button_box.pack_end(view_log_button, expand=False, fill=False)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def build_image_clicked_cb(self, button):
|
||||
self.builder.build_image()
|
||||
|
||||
@@ -213,7 +183,7 @@ class PackageSelectionPage (HobPage):
|
||||
image_total_size += (51200 * 1024)
|
||||
image_total_size_str = HobPage._size_to_string(image_total_size)
|
||||
|
||||
self.label.set_label("Packages included: %s\nSelected packages size: %s\nTotal image size: %s" %
|
||||
self.label.set_text("Packages included: %s\nSelected packages size: %s\nTotal image size: %s" %
|
||||
(selected_packages_num, selected_packages_size_str, image_total_size_str))
|
||||
self.ins.show_indicator_icon("Included", selected_packages_num)
|
||||
|
||||
@@ -231,7 +201,7 @@ class PackageSelectionPage (HobPage):
|
||||
self.refresh_selection()
|
||||
if not self.builder.customized:
|
||||
self.builder.customized = True
|
||||
self.builder.configuration.selected_image = self.recipe_model.__custom_image__
|
||||
self.builder.configuration.selected_image = self.recipe_model.__dummy_image__
|
||||
self.builder.rcppkglist_populated()
|
||||
|
||||
self.builder.window_sensitive(True)
|
||||
@@ -277,20 +247,3 @@ class PackageSelectionPage (HobPage):
|
||||
def after_fadeout_checkin_include(self, table, ctrl, cell, tree):
|
||||
tree.set_model(self.package_model.tree_model(self.pages[0]['filter']))
|
||||
tree.expand_all()
|
||||
|
||||
def foreach_cell_change_font(self, model, path, iter, paths=None):
|
||||
# Changed the font for a group cells
|
||||
if path and iter and path[0] == paths[0]:
|
||||
self.package_model.set(iter, self.package_model.COL_FONT, "bold")
|
||||
else:
|
||||
if iter and model.iter_parent(iter) == None:
|
||||
self.package_model.set(iter, self.package_model.COL_FONT, '11')
|
||||
else:
|
||||
self.package_model.set(iter, self.package_model.COL_FONT, '10')
|
||||
|
||||
def table_selected_cb(self, selection):
|
||||
model, paths = selection.get_selected_rows()
|
||||
if paths:
|
||||
child_path = self.package_model.convert_vpath_to_path(model, paths[0])
|
||||
self.package_model.foreach(self.foreach_cell_change_font, child_path)
|
||||
|
||||
|
||||
@@ -134,15 +134,13 @@ class RecipeSelectionPage (HobPage):
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def included_clicked_cb(self, button):
|
||||
self.ins.set_current_page(0)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.eventbox = self.add_onto_top_bar(None, 73)
|
||||
self.label = gtk.Label()
|
||||
self.eventbox = self.add_onto_top_bar(self.label, 73)
|
||||
self.pack_start(self.eventbox, expand=False, fill=False)
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
# set visible members
|
||||
# set visiable members
|
||||
self.ins = HobNotebook()
|
||||
self.tables = [] # we need modify table when the dialog is shown
|
||||
# append the tabs in order
|
||||
@@ -155,7 +153,10 @@ class RecipeSelectionPage (HobPage):
|
||||
if page['name'] == "Included":
|
||||
tab.connect("button-release-event", self.button_click_cb)
|
||||
tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include)
|
||||
self.ins.append_page(tab, page['name'], page['tooltip'])
|
||||
label = gtk.Label(page['name'])
|
||||
label.set_selectable(False)
|
||||
label.set_tooltip_text(page['tooltip'])
|
||||
self.ins.append_page(tab, label)
|
||||
self.tables.append(tab)
|
||||
|
||||
self.ins.set_entry("Search recipes:")
|
||||
@@ -201,6 +202,7 @@ class RecipeSelectionPage (HobPage):
|
||||
def refresh_selection(self):
|
||||
self.builder.configuration.selected_image = self.recipe_model.get_selected_image()
|
||||
_, self.builder.configuration.selected_recipes = self.recipe_model.get_selected_recipes()
|
||||
self.label.set_text("Recipes included: %s" % len(self.builder.configuration.selected_recipes))
|
||||
self.ins.show_indicator_icon("Included", len(self.builder.configuration.selected_recipes))
|
||||
|
||||
def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
|
||||
@@ -217,7 +219,7 @@ class RecipeSelectionPage (HobPage):
|
||||
self.refresh_selection()
|
||||
if not self.builder.customized:
|
||||
self.builder.customized = True
|
||||
self.builder.configuration.selected_image = self.recipe_model.__custom_image__
|
||||
self.builder.configuration.selected_image = self.recipe_model.__dummy_image__
|
||||
self.builder.rcppkglist_populated()
|
||||
|
||||
self.builder.window_sensitive(True)
|
||||
|
||||
@@ -76,9 +76,6 @@ class RunningBuild (gobject.GObject):
|
||||
'build-complete' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
'build-aborted' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
'task-started' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
@@ -88,9 +85,6 @@ class RunningBuild (gobject.GObject):
|
||||
'no-provider' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_PYOBJECT,)),
|
||||
'log' : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,)),
|
||||
}
|
||||
pids_to_task = {}
|
||||
tasks_to_iter = {}
|
||||
@@ -99,7 +93,6 @@ class RunningBuild (gobject.GObject):
|
||||
gobject.GObject.__init__ (self)
|
||||
self.model = RunningBuildModel()
|
||||
self.sequential = sequential
|
||||
self.buildaborted = False
|
||||
|
||||
def reset (self):
|
||||
self.pids_to_task.clear()
|
||||
@@ -129,8 +122,6 @@ class RunningBuild (gobject.GObject):
|
||||
parent = self.tasks_to_iter[(package, task)]
|
||||
|
||||
if(isinstance(event, logging.LogRecord)):
|
||||
if event.taskpid == 0 or event.levelno > logging.INFO:
|
||||
self.emit("log", "handle", event)
|
||||
# FIXME: this is a hack! More info in Yocto #1433
|
||||
# http://bugzilla.pokylinux.org/show_bug.cgi?id=1433, temporarily
|
||||
# mask the error message as it's not informative for the user.
|
||||
@@ -216,7 +207,6 @@ class RunningBuild (gobject.GObject):
|
||||
self.tasks_to_iter[(package, task)] = i
|
||||
|
||||
elif isinstance(event, bb.build.TaskBase):
|
||||
self.emit("log", "info", event._message)
|
||||
current = self.tasks_to_iter[(package, task)]
|
||||
parent = self.tasks_to_iter[(package, None)]
|
||||
|
||||
@@ -284,9 +274,7 @@ class RunningBuild (gobject.GObject):
|
||||
0))
|
||||
|
||||
# Emit the appropriate signal depending on the number of failures
|
||||
if self.buildaborted:
|
||||
self.emit ("build-aborted")
|
||||
elif (failures >= 1):
|
||||
if (failures >= 1):
|
||||
self.emit ("build-failed")
|
||||
else:
|
||||
self.emit ("build-succeeded")
|
||||
@@ -298,11 +286,7 @@ class RunningBuild (gobject.GObject):
|
||||
if pbar:
|
||||
pbar.set_text(event.msg)
|
||||
|
||||
elif isinstance(event, bb.event.DiskFull):
|
||||
self.buildaborted = True
|
||||
|
||||
elif isinstance(event, bb.command.CommandFailed):
|
||||
self.emit("log", "error", "Command execution failed: %s" % (event.error))
|
||||
if event.error.startswith("Exited with"):
|
||||
# If the command fails with an exit code we're done, emit the
|
||||
# generic signal for the UI to notify the user
|
||||
@@ -330,24 +314,7 @@ class RunningBuild (gobject.GObject):
|
||||
elif isinstance(event, bb.event.ParseCompleted) and pbar:
|
||||
pbar.hide()
|
||||
#using runqueue events as many as possible to update the progress bar
|
||||
elif isinstance(event, bb.runqueue.runQueueTaskFailed):
|
||||
self.emit("log", "error", "Task %s (%s) failed with exit code '%s'" % (event.taskid, event.taskstring, event.exitcode))
|
||||
elif isinstance(event, bb.runqueue.sceneQueueTaskFailed):
|
||||
self.emit("log", "warn", "Setscene task %s (%s) failed with exit code '%s' - real task will be run instead" \
|
||||
% (event.taskid, event.taskstring, event.exitcode))
|
||||
elif isinstance(event, (bb.runqueue.runQueueTaskStarted, bb.runqueue.sceneQueueTaskStarted)):
|
||||
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
|
||||
self.emit("log", "info", "Running setscene task %d of %d (%s)" % \
|
||||
(event.stats.completed + event.stats.active + event.stats.failed + 1,
|
||||
event.stats.total, event.taskstring))
|
||||
else:
|
||||
if event.noexec:
|
||||
tasktype = 'noexec task'
|
||||
else:
|
||||
tasktype = 'task'
|
||||
self.emit("log", "info", "Running %s %s of %s (ID: %s, %s)" % \
|
||||
(tasktype, event.stats.completed + event.stats.active + event.stats.failed + 1,
|
||||
event.stats.total, event.taskid, event.taskstring))
|
||||
message = {}
|
||||
message["eventname"] = bb.event.getName(event)
|
||||
num_of_completed = event.stats.completed + event.stats.failed
|
||||
@@ -356,10 +323,6 @@ class RunningBuild (gobject.GObject):
|
||||
message["title"] = ""
|
||||
message["task"] = event.taskstring
|
||||
self.emit("task-started", message)
|
||||
elif isinstance(event, bb.event.MultipleProviders):
|
||||
self.emit("log", "info", "multiple providers are available for %s%s (%s)" \
|
||||
% (event._is_runtime and "runtime " or "", event._item, ", ".join(event._candidates)))
|
||||
self.emit("log", "info", "consider defining a PREFERRED_PROVIDER entry to match %s" % (event._item))
|
||||
elif isinstance(event, bb.event.NoProvider):
|
||||
msg = ""
|
||||
if event._runtime:
|
||||
@@ -374,19 +337,6 @@ class RunningBuild (gobject.GObject):
|
||||
for reason in event._reasons:
|
||||
msg += ("%s\n" % reason)
|
||||
self.emit("no-provider", msg)
|
||||
self.emit("log", msg)
|
||||
else:
|
||||
if not isinstance(event, (bb.event.BuildBase,
|
||||
bb.event.StampUpdate,
|
||||
bb.event.ConfigParsed,
|
||||
bb.event.RecipeParsed,
|
||||
bb.event.RecipePreFinalise,
|
||||
bb.runqueue.runQueueEvent,
|
||||
bb.runqueue.runQueueExitWait,
|
||||
bb.event.OperationStarted,
|
||||
bb.event.OperationCompleted,
|
||||
bb.event.OperationProgress)):
|
||||
self.emit("log", "error", "Unknown event: %s" % (event.error if hasattr(event, 'error') else 'error'))
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -101,19 +101,7 @@ class HobTemplateFile(ConfigFile):
|
||||
return self.dictionary[var]
|
||||
else:
|
||||
return ""
|
||||
|
||||
def getVersion(self):
|
||||
contents = ConfigFile.readFile(self)
|
||||
|
||||
pattern = "^\s*(\S+)\s*=\s*(\".*?\")"
|
||||
|
||||
for line in contents:
|
||||
match = re.search(pattern, line)
|
||||
if match:
|
||||
if match.group(1) == "VERSION":
|
||||
return match.group(2).strip('"')
|
||||
return None
|
||||
|
||||
|
||||
def load(self):
|
||||
contents = ConfigFile.readFile(self)
|
||||
self.dictionary.clear()
|
||||
@@ -186,9 +174,6 @@ class TemplateMgr(gobject.GObject):
|
||||
self.image_bb.save()
|
||||
self.template_hob.save()
|
||||
|
||||
def getVersion(self, path):
|
||||
return HobTemplateFile(path).getVersion()
|
||||
|
||||
def load(self, path):
|
||||
self.template_hob = HobTemplateFile(path)
|
||||
self.dictionary = self.template_hob.load()
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
# bitbake which will allow more flexibility.
|
||||
|
||||
import os
|
||||
import bb
|
||||
|
||||
def which_terminal():
|
||||
term = bb.utils.which(os.environ["PATH"], "xterm")
|
||||
|
||||
@@ -24,7 +24,7 @@ import threading
|
||||
import xmlrpclib
|
||||
import bb
|
||||
import bb.event
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.progress import ProgressBar
|
||||
|
||||
# Package Model
|
||||
(COL_PKG_NAME) = (0)
|
||||
@@ -220,12 +220,8 @@ def main(server, eventHandler):
|
||||
|
||||
gtk.gdk.threads_enter()
|
||||
dep = DepExplorer()
|
||||
bardialog = gtk.Dialog(parent=dep)
|
||||
bardialog.set_default_size(400, 50)
|
||||
pbar = HobProgressBar()
|
||||
bardialog.vbox.pack_start(pbar)
|
||||
bardialog.show_all()
|
||||
bardialog.connect("delete-event", gtk.main_quit)
|
||||
pbar = ProgressBar(dep)
|
||||
pbar.connect("delete-event", gtk.main_quit)
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
progress_total = 0
|
||||
@@ -242,20 +238,19 @@ def main(server, eventHandler):
|
||||
if isinstance(event, bb.event.CacheLoadStarted):
|
||||
progress_total = event.total
|
||||
gtk.gdk.threads_enter()
|
||||
bardialog.set_title("Loading Cache")
|
||||
pbar.update(0)
|
||||
pbar.set_title("Loading Cache")
|
||||
pbar.update(0, progress_total)
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
if isinstance(event, bb.event.CacheLoadProgress):
|
||||
x = event.current
|
||||
gtk.gdk.threads_enter()
|
||||
pbar.update(x * 1.0 / progress_total)
|
||||
pbar.set_title('')
|
||||
pbar.update(x, progress_total)
|
||||
gtk.gdk.threads_leave()
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.event.CacheLoadCompleted):
|
||||
bardialog.hide()
|
||||
pbar.hide()
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.event.ParseStarted):
|
||||
@@ -263,21 +258,19 @@ def main(server, eventHandler):
|
||||
if progress_total == 0:
|
||||
continue
|
||||
gtk.gdk.threads_enter()
|
||||
pbar.update(0)
|
||||
bardialog.set_title("Processing recipes")
|
||||
|
||||
pbar.set_title("Processing recipes")
|
||||
pbar.update(0, progress_total)
|
||||
gtk.gdk.threads_leave()
|
||||
|
||||
if isinstance(event, bb.event.ParseProgress):
|
||||
x = event.current
|
||||
gtk.gdk.threads_enter()
|
||||
pbar.update(x * 1.0 / progress_total)
|
||||
pbar.set_title('')
|
||||
pbar.update(x, progress_total)
|
||||
gtk.gdk.threads_leave()
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.event.ParseCompleted):
|
||||
bardialog.hide()
|
||||
pbar.hide()
|
||||
continue
|
||||
|
||||
if isinstance(event, bb.event.DepTreeGenerated):
|
||||
|
||||
@@ -30,7 +30,7 @@ try:
|
||||
pygtk.require('2.0') # to be certain we don't have gtk+ 1.x !?!
|
||||
gtkver = gtk.gtk_version
|
||||
pygtkver = gtk.pygtk_version
|
||||
if gtkver < (2, 20, 0) or pygtkver < (2, 21, 0):
|
||||
if gtkver < (2, 18, 0) or pygtkver < (2, 16, 0):
|
||||
sys.exit("%s,\nYou have Gtk+ %s and PyGtk %s." % (requirements,
|
||||
".".join(map(str, gtkver)),
|
||||
".".join(map(str, pygtkver))))
|
||||
|
||||
@@ -119,7 +119,6 @@ def main(server, eventHandler, tf = TerminalFilter):
|
||||
console.setFormatter(format)
|
||||
logger.addHandler(console)
|
||||
if consolelogfile:
|
||||
bb.utils.mkdirhier(os.path.dirname(consolelogfile))
|
||||
consolelog = logging.FileHandler(consolelogfile)
|
||||
bb.msg.addDefaultlogFilter(consolelog)
|
||||
consolelog.setFormatter(format)
|
||||
|
||||
@@ -106,4 +106,4 @@ class TerminalFilter2(object):
|
||||
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
|
||||
|
||||
def main(server, eventHandler):
|
||||
return bb.ui.knotty.main(server, eventHandler, TerminalFilter2)
|
||||
bb.ui.knotty.main(server, eventHandler, TerminalFilter2)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
from __future__ import division
|
||||
import logging
|
||||
import os, sys, curses, itertools, time, subprocess
|
||||
import os, sys, curses, itertools, time
|
||||
import bb
|
||||
import xmlrpclib
|
||||
from bb import ui
|
||||
@@ -286,7 +286,7 @@ class NCursesUI:
|
||||
# bb.error("log data follows (%s)" % logfile)
|
||||
# number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
|
||||
# if number_of_lines:
|
||||
# subprocess.call('tail -n%s %s' % (number_of_lines, logfile), shell=True)
|
||||
# os.system('tail -n%s %s' % (number_of_lines, logfile))
|
||||
# else:
|
||||
# f = open(logfile, "r")
|
||||
# while True:
|
||||
|
||||
@@ -26,7 +26,6 @@ import logging
|
||||
import bb
|
||||
import bb.msg
|
||||
import multiprocessing
|
||||
import fcntl
|
||||
from commands import getstatusoutput
|
||||
from contextlib import contextmanager
|
||||
|
||||
@@ -109,10 +108,130 @@ def vercmp(ta, tb):
|
||||
r = vercmp_part(ra, rb)
|
||||
return r
|
||||
|
||||
def vercmp_string(a, b):
|
||||
ta = split_version(a)
|
||||
tb = split_version(b)
|
||||
return vercmp(ta, tb)
|
||||
_package_weights_ = {"pre":-2, "p":0, "alpha":-4, "beta":-3, "rc":-1} # dicts are unordered
|
||||
_package_ends_ = ["pre", "p", "alpha", "beta", "rc", "cvs", "bk", "HEAD" ] # so we need ordered list
|
||||
|
||||
def relparse(myver):
|
||||
"""Parses the last elements of a version number into a triplet, that can
|
||||
later be compared.
|
||||
"""
|
||||
|
||||
number = 0
|
||||
p1 = 0
|
||||
p2 = 0
|
||||
mynewver = myver.split('_')
|
||||
if len(mynewver) == 2:
|
||||
# an _package_weights_
|
||||
number = float(mynewver[0])
|
||||
match = 0
|
||||
for x in _package_ends_:
|
||||
elen = len(x)
|
||||
if mynewver[1][:elen] == x:
|
||||
match = 1
|
||||
p1 = _package_weights_[x]
|
||||
try:
|
||||
p2 = float(mynewver[1][elen:])
|
||||
except:
|
||||
p2 = 0
|
||||
break
|
||||
if not match:
|
||||
# normal number or number with letter at end
|
||||
divider = len(myver)-1
|
||||
if myver[divider:] not in "1234567890":
|
||||
# letter at end
|
||||
p1 = ord(myver[divider:])
|
||||
number = float(myver[0:divider])
|
||||
else:
|
||||
number = float(myver)
|
||||
else:
|
||||
# normal number or number with letter at end
|
||||
divider = len(myver)-1
|
||||
if myver[divider:] not in "1234567890":
|
||||
#letter at end
|
||||
p1 = ord(myver[divider:])
|
||||
number = float(myver[0:divider])
|
||||
else:
|
||||
number = float(myver)
|
||||
return [number, p1, p2]
|
||||
|
||||
__vercmp_cache__ = {}
|
||||
|
||||
def vercmp_string(val1, val2):
|
||||
"""This takes two version strings and returns an integer to tell you whether
|
||||
the versions are the same, val1>val2 or val2>val1.
|
||||
"""
|
||||
|
||||
# quick short-circuit
|
||||
if val1 == val2:
|
||||
return 0
|
||||
valkey = val1 + " " + val2
|
||||
|
||||
# cache lookup
|
||||
try:
|
||||
return __vercmp_cache__[valkey]
|
||||
try:
|
||||
return - __vercmp_cache__[val2 + " " + val1]
|
||||
except KeyError:
|
||||
pass
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# consider 1_p2 vc 1.1
|
||||
# after expansion will become (1_p2,0) vc (1,1)
|
||||
# then 1_p2 is compared with 1 before 0 is compared with 1
|
||||
# to solve the bug we need to convert it to (1,0_p2)
|
||||
# by splitting _prepart part and adding it back _after_expansion
|
||||
|
||||
val1_prepart = val2_prepart = ''
|
||||
if val1.count('_'):
|
||||
val1, val1_prepart = val1.split('_', 1)
|
||||
if val2.count('_'):
|
||||
val2, val2_prepart = val2.split('_', 1)
|
||||
|
||||
# replace '-' by '.'
|
||||
# FIXME: Is it needed? can val1/2 contain '-'?
|
||||
|
||||
val1 = val1.split("-")
|
||||
if len(val1) == 2:
|
||||
val1[0] = val1[0] + "." + val1[1]
|
||||
val2 = val2.split("-")
|
||||
if len(val2) == 2:
|
||||
val2[0] = val2[0] + "." + val2[1]
|
||||
|
||||
val1 = val1[0].split('.')
|
||||
val2 = val2[0].split('.')
|
||||
|
||||
# add back decimal point so that .03 does not become "3" !
|
||||
for x in xrange(1, len(val1)):
|
||||
if val1[x][0] == '0' :
|
||||
val1[x] = '.' + val1[x]
|
||||
for x in xrange(1, len(val2)):
|
||||
if val2[x][0] == '0' :
|
||||
val2[x] = '.' + val2[x]
|
||||
|
||||
# extend varion numbers
|
||||
if len(val2) < len(val1):
|
||||
val2.extend(["0"]*(len(val1)-len(val2)))
|
||||
elif len(val1) < len(val2):
|
||||
val1.extend(["0"]*(len(val2)-len(val1)))
|
||||
|
||||
# add back _prepart tails
|
||||
if val1_prepart:
|
||||
val1[-1] += '_' + val1_prepart
|
||||
if val2_prepart:
|
||||
val2[-1] += '_' + val2_prepart
|
||||
# The above code will extend version numbers out so they
|
||||
# have the same number of digits.
|
||||
for x in xrange(0, len(val1)):
|
||||
cmp1 = relparse(val1[x])
|
||||
cmp2 = relparse(val2[x])
|
||||
for y in xrange(0, 3):
|
||||
myret = cmp1[y] - cmp2[y]
|
||||
if myret != 0:
|
||||
__vercmp_cache__[valkey] = myret
|
||||
return myret
|
||||
__vercmp_cache__[valkey] = 0
|
||||
return 0
|
||||
|
||||
def explode_deps(s):
|
||||
"""
|
||||
@@ -423,6 +542,8 @@ def preserved_envvars():
|
||||
'BB_PRESERVE_ENV',
|
||||
'BB_ENV_WHITELIST',
|
||||
'BB_ENV_EXTRAWHITE',
|
||||
'LANG',
|
||||
'_',
|
||||
]
|
||||
return v + preserved_envvars_exported() + preserved_envvars_exported_interactive()
|
||||
|
||||
@@ -720,8 +841,6 @@ def which(path, item, direction = 0):
|
||||
for p in paths:
|
||||
next = os.path.join(p, item)
|
||||
if os.path.exists(next):
|
||||
if not os.path.isabs(next):
|
||||
next = os.path.abspath(next)
|
||||
return next
|
||||
|
||||
return ""
|
||||
@@ -753,7 +872,3 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
|
||||
|
||||
def cpu_count():
|
||||
return multiprocessing.cpu_count()
|
||||
|
||||
def nonblockingfd(fd):
|
||||
fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<para>
|
||||
Recall that earlier the manual discussed how to use an existing toolchain
|
||||
tarball that had been installed into <filename>/opt/poky</filename>,
|
||||
which is outside of the build directory
|
||||
which is outside of the Yocto Project build tree
|
||||
(see the section "<link linkend='using-an-existing-toolchain-tarball'>Using an Existing
|
||||
Toolchain Tarball)</link>".
|
||||
And, that sourcing your architecture-specific environment setup script
|
||||
@@ -21,7 +21,7 @@
|
||||
for example, <filename>configure.sh</filename> can find pre-generated
|
||||
test results for tests that need target hardware on which to run.
|
||||
These conditions allow you to easily use the toolchain outside of the
|
||||
OpenEmbedded build environment on both autotools-based projects and
|
||||
Yocto Project build environment on both autotools-based projects and
|
||||
Makefile-based projects.
|
||||
</para>
|
||||
|
||||
|
||||
736
documentation/adt-manual/adt-eclipse.xml
Normal file
736
documentation/adt-manual/adt-eclipse.xml
Normal file
@@ -0,0 +1,736 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='adt-eclipse'>
|
||||
<title>Working Within Eclipse</title>
|
||||
|
||||
<para>
|
||||
The Eclipse IDE is a popular development environment and it fully supports
|
||||
development using Yocto Project.
|
||||
When you install and configure the Eclipse Yocto Project Plug-in into
|
||||
the Eclipse IDE, you maximize your Yocto Project design experience.
|
||||
Installing and configuring the Plug-in results in an environment that
|
||||
has extensions specifically designed to let you more easily develop software.
|
||||
These extensions allow for cross-compilation, deployment, and execution of
|
||||
your output into a QEMU emulation session.
|
||||
You can also perform cross-debugging and profiling.
|
||||
The environment also supports a suite of tools that allows you to perform
|
||||
remote profiling, tracing, collection of power data, collection of
|
||||
latency data, and collection of performance data.
|
||||
</para>
|
||||
<para>
|
||||
This section describes how to install and configure the Eclipse IDE
|
||||
Yocto Plug-in and how to use it to develop your Yocto Project.
|
||||
</para>
|
||||
|
||||
<section id='setting-up-the-eclipse-ide'>
|
||||
<title>Setting Up the Eclipse IDE</title>
|
||||
|
||||
<para>
|
||||
To develop within the Eclipse IDE, you need to do the following:
|
||||
<orderedlist>
|
||||
<listitem><para>Install the optimal version of the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>Configure the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>Install the Eclipse Yocto Plug-in.</para></listitem>
|
||||
<listitem><para>Configure the Eclipse Yocto Plug-in.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<section id='installing-eclipse-ide'>
|
||||
<title>Installing the Eclipse IDE</title>
|
||||
|
||||
<para>
|
||||
It is recommended that you have the Indigo 3.7.2 version of the
|
||||
Eclipse IDE installed on your development system.
|
||||
If you don’t have this version, you can find it at
|
||||
<ulink url='&ECLIPSE_MAIN_URL;'></ulink>.
|
||||
From that site, choose the Eclipse Classic version particular to your development
|
||||
host.
|
||||
This version contains the Eclipse Platform, the Java Development
|
||||
Tools (JDT), and the Plug-in Development Environment.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you have downloaded the tarball, extract it into a clean
|
||||
directory.
|
||||
For example, the following commands unpack and install the Eclipse IDE
|
||||
tarball found in the <filename>Downloads</filename> area
|
||||
into a clean directory using the default name <filename>eclipse</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~
|
||||
$ tar -xzvf ~/Downloads/eclipse-SDK-3.7.1-linux-gtk-x86_64.tar.gz
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One issue exists that you need to be aware of regarding the Java
|
||||
Virtual machine’s garbage collection (GC) process.
|
||||
The GC process does not clean up the permanent generation
|
||||
space (PermGen).
|
||||
This space stores metadata descriptions of classes.
|
||||
The default value is set too small and it could trigger an
|
||||
out-of-memory error such as the following:
|
||||
<literallayout class='monospaced'>
|
||||
Java.lang.OutOfMemoryError: PermGen space
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This error causes the application to hang.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To fix this issue, you can use the <filename>--vmargs</filename>
|
||||
option when you start Eclipse to increase the size of the permanent generation space:
|
||||
<literallayout class='monospaced'>
|
||||
eclipse --vmargs --XX:PermSize=256M
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='configuring-the-eclipse-ide'>
|
||||
<title>Configuring the Eclipse IDE</title>
|
||||
|
||||
<para>
|
||||
Before installing and configuring the Eclipse Yocto Plug-in, you need to configure
|
||||
the Eclipse IDE.
|
||||
Follow these general steps to configure Eclipse:
|
||||
<orderedlist>
|
||||
<listitem><para>Start the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>Make sure you are in your Workbench and select
|
||||
"Install New Software" from the "Help" pull-down menu.
|
||||
</para></listitem>
|
||||
<listitem><para>Select <filename>indigo - &ECLIPSE_INDIGO_URL;</filename>
|
||||
from the "Work with:" pull-down menu.</para></listitem>
|
||||
<listitem><para>Expand the box next to <filename>Programming Languages</filename>
|
||||
and select the <filename>Autotools Support for CDT (incubation)</filename>
|
||||
and <filename>C/C++ Development Tools</filename> boxes.</para></listitem>
|
||||
<listitem><para>Expand the box next to "Linux Tools" and select the
|
||||
"LTTng - Linux Tracing Toolkit(incubation)" boxes.</para></listitem>
|
||||
<listitem><para>Complete the installation and restart the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>After the Eclipse IDE restarts and from the Workbench, select
|
||||
"Install New Software" from the "Help" pull-down menu.</para></listitem>
|
||||
<listitem><para>Click the
|
||||
"Available Software Sites" link.</para></listitem>
|
||||
<listitem><para>Check the box next to
|
||||
<filename>&ECLIPSE_UPDATES_URL;</filename>
|
||||
and click "OK".</para></listitem>
|
||||
<listitem><para>Select <filename>&ECLIPSE_UPDATES_URL;</filename>
|
||||
from the "Work with:" pull-down menu.</para></listitem>
|
||||
<listitem><para>Check the box next to <filename>TM and RSE Main Features</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para>Expand the box next to <filename>TM and RSE Optional Add-ons</filename>
|
||||
and select every item except <filename>RSE Unit Tests</filename> and
|
||||
<filename>RSE WinCE Services (incubation)</filename>.</para></listitem>
|
||||
<listitem><para>Complete the installation and restart the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>If necessary, select
|
||||
"Install New Software" from the "Help" pull-down menu so you can click the
|
||||
"Available Software Sites" link again.</para></listitem>
|
||||
<listitem><para>After clicking "Available Software Sites", check the box next to
|
||||
<filename>http://download.eclipse.org/tools/cdt/releases/indigo</filename>
|
||||
and click "OK".</para></listitem>
|
||||
<listitem><para>Select <filename>&ECLIPSE_INDIGO_CDT_URL;</filename>
|
||||
from the "Work with:" pull-down menu.</para></listitem>
|
||||
<listitem><para>Check the box next to <filename>CDT Main Features</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para>Expand the box next to <filename>CDT Optional Features</filename>
|
||||
and select <filename>C/C++ Remote Launch</filename> and
|
||||
<filename>Target Communication Framework (incubation)</filename>.</para></listitem>
|
||||
<listitem><para>Complete the installation and restart the Eclipse IDE.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='installing-the-eclipse-yocto-plug-in'>
|
||||
<title>Installing or Accessing the Eclipse Yocto Plug-in</title>
|
||||
|
||||
<para>
|
||||
You can install the Eclipse Yocto Plug-in into the Eclipse IDE
|
||||
one of two ways: use the Yocto Project update site to install the pre-built plug-in,
|
||||
or build and install the plug-in from the latest source code.
|
||||
If you don't want to permanently install the plug-in but just want to try it out
|
||||
within the Eclipse environment, you can import the plug-in project from the
|
||||
Yocto Project source repositories.
|
||||
</para>
|
||||
|
||||
<section id='new-software'>
|
||||
<title>Installing the Pre-built Plug-in from the Yocto Project Eclipse Update Site</title>
|
||||
|
||||
<para>
|
||||
To install the Eclipse Yocto Plug-in from the update site,
|
||||
follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Start up the Eclipse IDE.</para></listitem>
|
||||
<listitem><para>In Eclipse, select "Install New Software" from the "Help" menu.</para></listitem>
|
||||
<listitem><para>Click "Add..." in the "Work with:" area.</para></listitem>
|
||||
<listitem><para>Enter
|
||||
<filename>&ECLIPSE_DL_PLUGIN_URL;</filename>
|
||||
in the URL field and provide a meaningful name in the "Name" field.</para></listitem>
|
||||
<listitem><para>Click "OK" to have the entry added to the "Work with:"
|
||||
drop-down list.</para></listitem>
|
||||
<listitem><para>Select the entry for the plug-in from the "Work with:" drop-down
|
||||
list.</para></listitem>
|
||||
<listitem><para>Check the box next to <filename>Development tools and SDKs for Yocto Linux</filename>.
|
||||
</para></listitem>
|
||||
<listitem><para>Complete the remaining software installation steps and
|
||||
then restart the Eclipse IDE to finish the installation of the plug-in.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='zip-file-method'>
|
||||
<title>Installing the Plug-in Using the Latest Source Code</title>
|
||||
<para>
|
||||
To install the Eclipse Yocto Plug-in from the latest source code, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Open a shell and create a Git repository with:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/eclipse-poky yocto-eclipse
|
||||
</literallayout>
|
||||
For this example, the repository is named
|
||||
<filename>~/yocto-eclipse</filename>.</para></listitem>
|
||||
<listitem><para>Locate the <filename>build.sh</filename> script in the
|
||||
Git repository you created in the previous step.
|
||||
The script is located in the <filename>scripts</filename>.</para></listitem>
|
||||
<listitem><para>Be sure to set and export the <filename>ECLIPSE_HOME</filename> environment
|
||||
variable to the top-level directory in which you installed the Indigo
|
||||
version of Eclipse.
|
||||
For example, if your Eclipse directory is <filename>$HOME/eclipse</filename>,
|
||||
use the following:
|
||||
<literallayout class='monospaced'>
|
||||
$ export ECLIPSE_HOME=$HOME/eclipse
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Run the <filename>build.sh</filename> script and provide the
|
||||
name of the Git branch along with the Yocto Project release you are
|
||||
using.
|
||||
Here is an example that uses the <filename>master</filename> Git repository
|
||||
and the <filename>1.1M4</filename> release:
|
||||
<literallayout class='monospaced'>
|
||||
$ scripts/build.sh master 1.1M4
|
||||
</literallayout>
|
||||
After running the script, the file
|
||||
<filename>org.yocto.sdk-<release>-<date>-archive.zip</filename>
|
||||
is in the current directory.</para></listitem>
|
||||
<listitem><para>If necessary, start the Eclipse IDE and be sure you are in the
|
||||
Workbench.</para></listitem>
|
||||
<listitem><para>Select "Install New Software" from the "Help" pull-down menu.
|
||||
</para></listitem>
|
||||
<listitem><para>Click "Add".</para></listitem>
|
||||
<listitem><para>Provide anything you want in the "Name" field.</para></listitem>
|
||||
<listitem><para>Click "Archive" and browse to the ZIP file you built
|
||||
in step four.
|
||||
This ZIP file should not be "unzipped", and must be the
|
||||
<filename>*archive.zip</filename> file created by running the
|
||||
<filename>build.sh</filename> script.</para></listitem>
|
||||
<listitem><para>Check the box next to the new entry in the installation window and complete
|
||||
the installation.</para></listitem>
|
||||
<listitem><para>Restart the Eclipse IDE if necessary.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At this point you should be able to configure the Eclipse Yocto Plug-in as described in the
|
||||
"<link linkend='configuring-the-eclipse-yocto-plug-in'>Configuring the Eclipse Yocto Plug-in</link>"
|
||||
section.</para>
|
||||
</section>
|
||||
|
||||
<section id='yocto-project-source'>
|
||||
<title>Importing the Plug-in Project into the Eclipse Environment</title>
|
||||
<para>
|
||||
Importing the Eclipse Yocto Plug-in project from the Yocto Project source repositories
|
||||
is useful when you want to try out the latest plug-in from the tip of plug-in's
|
||||
development tree.
|
||||
It is important to understand when you import the plug-in you are not installing
|
||||
it into the Eclipse application.
|
||||
Rather, you are importing the project and just using it.
|
||||
To import the plug-in project, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Open a shell and create a Git repository with:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/eclipse-poky yocto-eclipse
|
||||
</literallayout>
|
||||
For this example, the repository is named
|
||||
<filename>~/yocto-eclipse</filename>.</para></listitem>
|
||||
<listitem><para>In Eclipse, select "Import" from the "File" menu.</para></listitem>
|
||||
<listitem><para>Expand the "General" box and select "existing projects into workspace"
|
||||
and then click "Next".</para></listitem>
|
||||
<listitem><para>Select the root directory and browse to
|
||||
<filename>~/yocto-eclipse/plugins</filename>.</para></listitem>
|
||||
<listitem><para>Three plug-ins exist: "org.yocto.bc.ui", "org.yocto.sdk.ide", and
|
||||
"org.yocto.sdk.remotetools".
|
||||
Select and import all of them.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The left navigation pane in the Eclipse application shows the default projects.
|
||||
Right-click on one of these projects and run it as an Eclipse application.
|
||||
This brings up a second instance of Eclipse IDE that has the Yocto Plug-in.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='configuring-the-eclipse-yocto-plug-in'>
|
||||
<title>Configuring the Eclipse Yocto Plug-in</title>
|
||||
|
||||
<para>
|
||||
Configuring the Eclipse Yocto Plug-in involves setting the Cross
|
||||
Compiler options and the Target options.
|
||||
The configurations you choose become the default settings for all projects.
|
||||
You do have opportunities to change them later when
|
||||
you configure the project (see the following section).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To start, you need to do the following from within the Eclipse IDE:
|
||||
<itemizedlist>
|
||||
<listitem><para>Choose <filename>Windows -> Preferences</filename> to display
|
||||
the <filename>Preferences</filename> Dialog</para></listitem>
|
||||
<listitem><para>Click <filename>Yocto ADT</filename></para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<section id='configuring-the-cross-compiler-options'>
|
||||
<title>Configuring the Cross-Compiler Options</title>
|
||||
|
||||
<para>
|
||||
To configure the Cross Compiler Options, you must select the type of toolchain,
|
||||
point to the toolchain, specify the sysroot location, and select the target architecture.
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Selecting the Toolchain Type:</emphasis>
|
||||
Choose between <filename>Standalone pre-built toolchain</filename>
|
||||
and <filename>Build system derived toolchain</filename> for Cross
|
||||
Compiler Options.
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>
|
||||
<filename>Standalone Pre-built Toolchain:</filename></emphasis>
|
||||
Select this mode when you are using a stand-alone cross-toolchain.
|
||||
For example, suppose you are an application developer and do not
|
||||
need to build a target image.
|
||||
Instead, you just want to use an architecture-specific toolchain on an
|
||||
existing kernel and target root filesystem.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<filename>Build System Derived Toolchain:</filename></emphasis>
|
||||
Select this mode if the cross-toolchain has been installed and built
|
||||
as part of the Yocto Project build tree.
|
||||
When you select <filename>Build system derived toolchain</filename>,
|
||||
you are using the toolchain bundled
|
||||
inside the Yocto Project build tree.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Point to the Toolchain:</emphasis>
|
||||
If you are using a stand-alone pre-built toolchain, you should be pointing to the
|
||||
<filename>&YOCTO_ADTPATH_DIR;</filename> directory.
|
||||
This is the location for toolchains installed by the ADT Installer or by hand.
|
||||
Sections "<link linkend='configuring-and-running-the-adt-installer-script'>Configuring
|
||||
and Running the ADT Installer Script</link>" and
|
||||
"<link linkend='using-an-existing-toolchain-tarball'>Using a Cross-Toolchain
|
||||
Tarball</link>" describe two ways to install
|
||||
a stand-alone cross-toolchain in the
|
||||
<filename>/opt/poky</filename> directory.
|
||||
<note>It is possible to install a stand-alone cross-toolchain in a directory
|
||||
other than <filename>/opt/poky</filename>.
|
||||
However, doing so is discouraged.</note></para>
|
||||
<para>If you are using a system-derived toolchain, the path you provide
|
||||
for the <filename>Toolchain Root Location</filename>
|
||||
field is the Yocto Project's build directory.
|
||||
See section "<link linkend='using-the-toolchain-from-within-the-build-tree'>Using
|
||||
BitBake and the Yocto Project Build Tree</link>" for
|
||||
information on how to install the toolchain into the Yocto
|
||||
Project build tree.</para></listitem>
|
||||
<listitem><para><emphasis>Specify the Sysroot Location:</emphasis>
|
||||
This location is where the root filesystem for the
|
||||
target hardware is created on the development system by the ADT Installer.
|
||||
The QEMU user-space tools, the
|
||||
NFS boot process, and the cross-toolchain all use the sysroot location.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Select the Target Architecture:</emphasis>
|
||||
The target architecture is the type of hardware you are
|
||||
going to use or emulate.
|
||||
Use the pull-down <filename>Target Architecture</filename> menu to make
|
||||
your selection.
|
||||
The pull-down menu should have the supported architectures.
|
||||
If the architecture you need is not listed in the menu, you
|
||||
will need to build the image.
|
||||
See the "<ulink url='&YOCTO_DOCS_QS_URL;#building-image'>Building an Image</ulink>" section
|
||||
of The Yocto Project Quick Start for more information.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='configuring-the-target-options'>
|
||||
<title>Configuring the Target Options</title>
|
||||
|
||||
<para>
|
||||
You can choose to emulate hardware using the QEMU emulator, or you
|
||||
can choose to run your image on actual hardware.
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis><filename>QEMU:</filename></emphasis> Select this option if
|
||||
you will be using the QEMU emulator.
|
||||
If you are using the emulator, you also need to locate the kernel
|
||||
and specify any custom options.</para>
|
||||
<para>If you selected <filename>Build system derived toolchain</filename>,
|
||||
the target kernel you built will be located in the
|
||||
Yocto Project build tree in <filename>tmp/deploy/images</filename> directory.
|
||||
If you selected <filename>Standalone pre-built toolchain</filename>, the
|
||||
pre-built image you downloaded is located
|
||||
in the directory you specified when you downloaded the image.</para>
|
||||
<para>Most custom options are for advanced QEMU users to further
|
||||
customize their QEMU instance.
|
||||
These options are specified between paired angled brackets.
|
||||
Some options must be specified outside the brackets.
|
||||
In particular, the options <filename>serial</filename>,
|
||||
<filename>nographic</filename>, and <filename>kvm</filename> must all
|
||||
be outside the brackets.
|
||||
Use the <filename>man qemu</filename> command to get help on all the options
|
||||
and their use.
|
||||
The following is an example:
|
||||
<literallayout class='monospaced'>
|
||||
serial ‘<-m 256 -full-screen>’
|
||||
</literallayout></para>
|
||||
<para>
|
||||
Regardless of the mode, Sysroot is already defined as part of the
|
||||
Cross Compiler Options configuration in the
|
||||
<filename>Sysroot Location:</filename> field.</para></listitem>
|
||||
<listitem><para><emphasis><filename>External HW:</filename></emphasis> Select this option
|
||||
if you will be using actual hardware.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Click the <filename>OK</filename> button to save your plug-in configurations.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='creating-the-project'>
|
||||
<title>Creating the Project</title>
|
||||
|
||||
<para>
|
||||
You can create two types of projects: Autotools-based, or Makefile-based.
|
||||
This section describes how to create Autotools-based projects from within
|
||||
the Eclipse IDE.
|
||||
For information on creating Makefile-based projects in a terminal window, see the section
|
||||
"<link linkend='using-the-command-line'>Using the Command Line</link>".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To create a project based on a Yocto template and then display the source code,
|
||||
follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Select <filename>File -> New -> Project</filename>.</para></listitem>
|
||||
<listitem><para>Double click <filename>CC++</filename>.</para></listitem>
|
||||
<listitem><para>Double click <filename>C Project</filename> to create the project.</para></listitem>
|
||||
<listitem><para>Expand <filename>Yocto ADT Project</filename>.</para></listitem>
|
||||
<listitem><para>Select <filename>Hello World ANSI C Autotools Project</filename>.
|
||||
This is an Autotools-based project based on a Yocto Project template.</para></listitem>
|
||||
<listitem><para>Put a name in the <filename>Project name:</filename> field.
|
||||
Do not use hyphens as part of the name.</para></listitem>
|
||||
<listitem><para>Click <filename>Next</filename>.</para></listitem>
|
||||
<listitem><para>Add information in the <filename>Author</filename> and
|
||||
<filename>Copyright notice</filename> fields.</para></listitem>
|
||||
<listitem><para>Be sure the <filename>License</filename> field is correct.</para></listitem>
|
||||
<listitem><para>Click <filename>Finish</filename>.</para></listitem>
|
||||
<listitem><para>If the "open perspective" prompt appears, click "Yes" so that you
|
||||
in the C/C++ perspective.</para></listitem>
|
||||
<listitem><para>The left-hand navigation pane shows your project.
|
||||
You can display your source by double clicking the project's source file.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='configuring-the-cross-toolchains'>
|
||||
<title>Configuring the Cross-Toolchains</title>
|
||||
|
||||
<para>
|
||||
The earlier section, "<link linkend='configuring-the-eclipse-yocto-plug-in'>Configuring
|
||||
the Eclipse Yocto Plug-in</link>", sets up the default project
|
||||
configurations.
|
||||
You can override these settings for a given project by following these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Select <filename>Project -> Change Yocto Project Settings</filename>:
|
||||
This selection brings up the <filename>Project Yocto Settings</filename> Dialog
|
||||
and allows you to make changes specific to an individual project.
|
||||
</para>
|
||||
<para>By default, the Cross Compiler Options and Target Options for a project
|
||||
are inherited from settings you provide using the <filename>Preferences</filename>
|
||||
Dialog as described earlier
|
||||
in the "<link linkend='configuring-the-eclipse-yocto-plug-in'>Configuring the Eclipse
|
||||
Yocto Plug-in</link>" section.
|
||||
The <filename>Project Yocto Settings</filename>
|
||||
Dialog allows you to override those default settings
|
||||
for a given project.</para></listitem>
|
||||
<listitem><para>Make your configurations for the project and click "OK".</para></listitem>
|
||||
<listitem><para>Select <filename>Project -> Reconfigure Project</filename>:
|
||||
This selection reconfigures the project by running
|
||||
<filename>autogen.sh</filename> in the workspace for your project.
|
||||
The script also runs <filename>libtoolize</filename>, <filename>aclocal</filename>,
|
||||
<filename>autoconf</filename>, <filename>autoheader</filename>,
|
||||
<filename>automake --a</filename>, and
|
||||
<filename>./configure</filename>.
|
||||
Click on the <filename>Console</filename> tab beneath your source code to
|
||||
see the results of reconfiguring your project.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='building-the-project'>
|
||||
<title>Building the Project</title>
|
||||
|
||||
<para>
|
||||
To build the project, select <filename>Project -> Build Project</filename>.
|
||||
The console should update and you can note the cross-compiler you are using.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='starting-qemu-in-user-space-nfs-mode'>
|
||||
<title>Starting QEMU in User Space NFS Mode</title>
|
||||
|
||||
<para>
|
||||
To start the QEMU emulator from within Eclipse, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Expose the <filename>Run -> External Tools</filename> menu.
|
||||
Your image should appear as a selectable menu item.
|
||||
</para></listitem>
|
||||
<listitem><para>Select your image from the menu to launch the
|
||||
emulator in a new window.</para></listitem>
|
||||
<listitem><para>If needed, enter your host root password in the shell window at the prompt.
|
||||
This sets up a <filename>Tap 0</filename> connection needed for running in user-space
|
||||
NFS mode.</para></listitem>
|
||||
<listitem><para>Wait for QEMU to launch.</para></listitem>
|
||||
<listitem><para>Once QEMU launches, you can begin operating within that
|
||||
environment.
|
||||
For example, you could determine the IP Address
|
||||
for the user-space NFS by using the <filename>ifconfig</filename> command.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='deploying-and-debugging-the-application'>
|
||||
<title>Deploying and Debugging the Application</title>
|
||||
|
||||
<para>
|
||||
Once the QEMU emulator is running the image, using the Eclipse IDE
|
||||
you can deploy your application and use the emulator to perform debugging.
|
||||
Follow these steps to deploy the application.
|
||||
<orderedlist>
|
||||
<listitem><para>Select <filename>Run -> Debug Configurations...</filename></para></listitem>
|
||||
<listitem><para>In the left area, expand <filename>C/C++Remote Application</filename>.</para></listitem>
|
||||
<listitem><para>Locate your project and select it to bring up a new
|
||||
tabbed view in the <filename>Debug Configurations</filename> Dialog.</para></listitem>
|
||||
<listitem><para>Enter the absolute path into which you want to deploy
|
||||
the application.
|
||||
Use the <filename>Remote Absolute File Path for C/C++Application:</filename> field.
|
||||
For example, enter <filename>/usr/bin/<programname></filename>.</para></listitem>
|
||||
<listitem><para>Click on the <filename>Debugger</filename> tab to see the cross-tool debugger
|
||||
you are using.</para></listitem>
|
||||
<listitem><para>Click on the <filename>Main</filename> tab.</para></listitem>
|
||||
<listitem><para>Create a new connection to the QEMU instance
|
||||
by clicking on <filename>new</filename>.</para></listitem>
|
||||
<listitem><para>Select <filename>TCF</filename>, which means Target Communication
|
||||
Framework.</para></listitem>
|
||||
<listitem><para>Click <filename>Next</filename>.</para></listitem>
|
||||
<listitem><para>Clear out the <filename>host name</filename> field and enter the IP Address
|
||||
determined earlier.</para></listitem>
|
||||
<listitem><para>Click <filename>Finish</filename> to close the
|
||||
<filename>New Connections</filename> Dialog.</para></listitem>
|
||||
<listitem><para>Use the drop-down menu now in the <filename>Connection</filename> field and pick
|
||||
the IP Address you entered.</para></listitem>
|
||||
<listitem><para>Click <filename>Debug</filename> to bring up a login screen
|
||||
and login.</para></listitem>
|
||||
<listitem><para>Accept the debug perspective.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='running-user-space-tools'>
|
||||
<title>Running User-Space Tools</title>
|
||||
|
||||
<para>
|
||||
As mentioned earlier in the manual, several tools exist that enhance
|
||||
your development experience.
|
||||
These tools are aids in developing and debugging applications and images.
|
||||
You can run these user-space tools from within the Eclipse IDE through the
|
||||
<filename>YoctoTools</filename> menu.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you pick a tool, you need to configure it for the remote target.
|
||||
Every tool needs to have the connection configured.
|
||||
You must select an existing TCF-based RSE connection to the remote target.
|
||||
If one does not exist, click <filename>New</filename> to create one.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here are some specifics about the remote tools:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis><filename>OProfile</filename>:</emphasis> Selecting this tool causes
|
||||
the <filename>oprofile-server</filename> on the remote target to launch on
|
||||
the local host machine.
|
||||
The <filename>oprofile-viewer</filename> must be installed on the local host machine and the
|
||||
<filename>oprofile-server</filename> must be installed on the remote target,
|
||||
respectively, in order to use.
|
||||
You must compile and install the <filename>oprofile-viewer</filename> from the source code
|
||||
on your local host machine.
|
||||
Furthermore, in order to convert the target's sample format data into a form that the
|
||||
host can use, you must have <filename>oprofile</filename> version 0.9.4 or
|
||||
greater installed on the host.</para>
|
||||
<para>You can locate both the viewer and server from
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit/cgit.cgi/oprofileui/'></ulink>.
|
||||
<note>The <filename>oprofile-server</filename> is installed by default on
|
||||
the <filename>core-image-sato-sdk</filename> image.</note></para></listitem>
|
||||
<listitem><para><emphasis><filename>Lttng-ust</filename>:</emphasis> Selecting this tool runs
|
||||
<filename>usttrace</filename> on the remote target, transfers the output data back
|
||||
to the local host machine, and uses the <filename>lttng</filename> Eclipse plug-in to
|
||||
graphically display the output.
|
||||
For information on how to use <filename>lttng</filename> to trace an application, see
|
||||
<ulink url='http://lttng.org/files/ust/manual/ust.html'></ulink>.</para>
|
||||
<para>For <filename>Application</filename>, you must supply the absolute path name of the
|
||||
application to be traced by user mode <filename>lttng</filename>.
|
||||
For example, typing <filename>/path/to/foo</filename> triggers
|
||||
<filename>usttrace /path/to/foo</filename> on the remote target to trace the
|
||||
program <filename>/path/to/foo</filename>.</para>
|
||||
<para><filename>Argument</filename> is passed to <filename>usttrace</filename>
|
||||
running on the remote target.</para>
|
||||
<para>Before you use the <filename>lttng-ust</filename> tool, you need to setup
|
||||
the <filename>lttng</filename> Eclipse plug-in and create a <filename>lttng</filename>
|
||||
project.
|
||||
Do the following:
|
||||
<orderedlist>
|
||||
<listitem><para>Follow these
|
||||
<ulink url='http://wiki.eclipse.org/Linux_Tools_Project/LTTng#Downloading_and_installing_the_LTTng_parser_library'>instructions</ulink>
|
||||
to download and install the <filename>lttng</filename> parser library.
|
||||
</para></listitem>
|
||||
<listitem><para>Select <filename>Window -> Open Perspective -> Other</filename>
|
||||
and then select <filename>LTTng</filename>.</para></listitem>
|
||||
<listitem><para>Click <filename>OK</filename> to change the Eclipse perspective
|
||||
into the <filename>LTTng</filename> perspective.</para></listitem>
|
||||
<listitem><para>Create a new <filename>LTTng</filename> project by selecting
|
||||
<filename>File -> New -> Project</filename>.</para></listitem>
|
||||
<listitem><para>Choose <filename>LTTng -> LTTng Project</filename>.</para></listitem>
|
||||
<listitem><para>Click <filename>YoctoTools -> lttng-ust</filename> to start user mode
|
||||
<filename>lttng</filename> on the remote target.</para></listitem>
|
||||
</orderedlist></para>
|
||||
<para>After the output data has been transferred from the remote target back to the local
|
||||
host machine, new traces will be imported into the selected <filename>LTTng</filename> project.
|
||||
Then you can go to the <filename>LTTng</filename> project, right click the imported
|
||||
trace, and set the trace type as the <filename>LTTng</filename> kernel trace.
|
||||
Finally, right click the imported trace and select <filename>Open</filename>
|
||||
to display the data graphically.</para></listitem>
|
||||
<listitem><para><emphasis><filename>PowerTOP</filename>:</emphasis> Selecting this tool runs
|
||||
<filename>powertop</filename> on the remote target machine and displays the results in a
|
||||
new view called <filename>powertop</filename>.</para>
|
||||
<para><filename>Time to gather data(sec):</filename> is the time passed in seconds before data
|
||||
is gathered from the remote target for analysis.</para>
|
||||
<para><filename>show pids in wakeups list:</filename> corresponds to the
|
||||
<filename>-p</filename> argument
|
||||
passed to <filename>powertop</filename>.</para></listitem>
|
||||
<listitem><para><emphasis><filename>LatencyTOP and Perf</filename>:</emphasis>
|
||||
<filename>latencytop</filename> identifies system latency, while
|
||||
<filename>perf</filename> monitors the system's
|
||||
performance counter registers.
|
||||
Selecting either of these tools causes an RSE terminal view to appear
|
||||
from which you can run the tools.
|
||||
Both tools refresh the entire screen to display results while they run.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='customizing-an-image-using-a-bitbake-commander-project-and-hob'>
|
||||
<title>Customizing an Image Using a BitBake Commander Project and Hob</title>
|
||||
|
||||
<para>
|
||||
Within Eclipse, you can create a Yocto BitBake Commander project,
|
||||
edit the metadata, and then use the
|
||||
<ulink url='&YOCTO_HOME_URL;/projects/hob'>Hob</ulink> to build a customized
|
||||
image all within one IDE.
|
||||
</para>
|
||||
|
||||
<section id='creating-the-yocto-bitbake-commander-project'>
|
||||
<title>Creating the Yocto BitBake Commander Project</title>
|
||||
|
||||
<para>
|
||||
To create a Yocto BitBake Commander project, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Select <filename>Window -> Open Perspective -> Other</filename>
|
||||
and then choose <filename>Bitbake Commander</filename>.</para></listitem>
|
||||
<listitem><para>Click <filename>OK</filename> to change the Eclipse perspective into the
|
||||
Bitbake Commander perspective.</para></listitem>
|
||||
<listitem><para>Select <filename>File -> New -> Project</filename> to create a new Yocto
|
||||
Bitbake Commander project.</para></listitem>
|
||||
<listitem><para>Choose <filename>Yocto Project Bitbake Commander -> New Yocto Project</filename>
|
||||
and click <filename>Next</filename>.</para></listitem>
|
||||
<listitem><para>Enter the Project Name and choose the Project Location.
|
||||
The Yocto project's metadata files will be put under the directory
|
||||
<filename><project_location>/<project_name></filename>.
|
||||
If that directory does not exist, you need to check
|
||||
the "Clone from Yocto Git Repository" box, which would execute a
|
||||
<filename>git clone</filename> command to get the Yocto project's metadata files.
|
||||
</para></listitem>
|
||||
<listitem><para>Select <filename>Finish</filename> to create the project.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='editing-the-metadata-files'>
|
||||
<title>Editing the Metadata Files</title>
|
||||
|
||||
<para>
|
||||
After you create the Yocto Bitbake Commander project, you can modify the metadata files
|
||||
by opening them in the project.
|
||||
When editing recipe files (<filename>.bb</filename> files), you can view BitBake
|
||||
variable values and information by hovering the mouse pointer over the variable name and
|
||||
waiting a few seconds.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To edit the metadata, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Select your Yocto Bitbake Commander project.</para></listitem>
|
||||
<listitem><para>Select <filename>File -> New -> Yocto BitBake Commander -> BitBake Recipe</filename>
|
||||
to open a new recipe wizard.</para></listitem>
|
||||
<listitem><para>Point to your source by filling in the "SRC_URL" field.
|
||||
For example, you can add a recipe in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-source-files'>Yocto Project Source Files</ulink>,
|
||||
input the "SRC_URL" as follows:
|
||||
<literallayout class='monospaced'>
|
||||
ftp://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Click "Populate" to calculate the archive md5, sha256,
|
||||
license checksum values and to auto-generate the recipe filename.</para></listitem>
|
||||
<listitem><para>Fill in the "Description" field.</para></listitem>
|
||||
<listitem><para>Be sure values for all required fields exist.</para></listitem>
|
||||
<listitem><para>Click <filename>Finish</filename>.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='buiding-and-customizing-the-image'>
|
||||
<title>Building and Customizing the Image</title>
|
||||
|
||||
<para>
|
||||
To build and customize the image in Eclipse, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Select your Yocto Bitbake Commander project.</para></listitem>
|
||||
<listitem><para>Select <filename>Project -> Launch HOB</filename>.</para></listitem>
|
||||
<listitem><para>Enter the build directory where you want to put your final images.</para></listitem>
|
||||
<listitem><para>Click <filename>OK</filename> to launch Hob.</para></listitem>
|
||||
<listitem><para>Use Hob to customize and build your own images.
|
||||
For information on Hob, see the
|
||||
<ulink url='&YOCTO_HOME_URL;/projects/hob'>Hob Project Page</ulink> on the
|
||||
Yocto Project website.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
@@ -3,51 +3,46 @@
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='adt-intro'>
|
||||
<title>Introduction</title>
|
||||
|
||||
<title>Application Development Toolkit (ADT) User's Guide</title>
|
||||
|
||||
<para>
|
||||
Welcome to the Yocto Project Application Developer's Guide.
|
||||
This manual provides information that lets you begin developing applications
|
||||
using the Yocto Project.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Yocto Project provides an application development environment based on
|
||||
an Application Development Toolkit (ADT) and the availability of stand-alone
|
||||
cross-development toolchains and other tools.
|
||||
This manual describes the ADT and how you can configure and install it,
|
||||
how to access and use the cross-development toolchains, how to
|
||||
customize the development packages installation,
|
||||
how to use command line development for both Autotools-based and Makefile-based projects,
|
||||
and an introduction to the Eclipse Yocto Plug-in.
|
||||
Welcome to the Application Development Toolkit User’s Guide. This manual provides
|
||||
information that lets you get going with the ADT to develop projects using the Yocto
|
||||
Project.
|
||||
</para>
|
||||
|
||||
<section id='book-intro'>
|
||||
<title>The Application Development Toolkit (ADT)</title>
|
||||
<title>Introducing the Application Development Toolkit (ADT)</title>
|
||||
|
||||
<para>
|
||||
Part of the Yocto Project development solution is an Application Development
|
||||
Toolkit (ADT).
|
||||
The ADT provides you with a custom-built, cross-development
|
||||
platform suited for developing a user-targeted product application.
|
||||
Fundamentally, the ADT consists of an architecture-specific cross-toolchain and
|
||||
a matching sysroot that are both built by the Yocto Project build system Poky.
|
||||
The toolchain and sysroot are based on a metadata configuration and extensions,
|
||||
which allows you to cross-develop on the host machine for the target.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Fundamentally, the ADT consists of the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>An architecture-specific cross-toolchain and matching
|
||||
sysroot both built by the OpenEmbedded build system, which uses Poky.
|
||||
The toolchain and sysroot are based on a metadata configuration and extensions,
|
||||
which allows you to cross-develop on the host machine for the target hardware.
|
||||
</para></listitem>
|
||||
<listitem><para>The Eclipse IDE Yocto Plug-in.</para></listitem>
|
||||
<listitem><para>The Quick EMUlator (QEMU), which lets you simulate target hardware.
|
||||
</para></listitem>
|
||||
<listitem><para>Various user-space tools that greatly enhance your application
|
||||
development experience.</para></listitem>
|
||||
</itemizedlist>
|
||||
Additionally, to provide an effective development platform, the Yocto Project
|
||||
makes available and suggests other tools you can use with the ADT.
|
||||
These other tools include the Eclipse IDE Yocto Plug-in, an emulator (QEMU),
|
||||
and various user-space tools that greatly enhance your development experience.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The resulting combination of the architecture-specific cross-toolchain and sysroot
|
||||
along with these additional tools yields a custom-built, cross-development platform
|
||||
for a user-targeted product.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='adt-components'>
|
||||
<title>ADT Components</title>
|
||||
|
||||
<para>
|
||||
This section provides a brief description of what comprises the ADT.
|
||||
</para>
|
||||
|
||||
<section id='the-cross-toolchain'>
|
||||
<title>The Cross-Toolchain</title>
|
||||
|
||||
@@ -55,7 +50,7 @@
|
||||
The cross-toolchain consists of a cross-compiler, cross-linker, and cross-debugger
|
||||
that are used to develop user-space applications for targeted hardware.
|
||||
This toolchain is created either by running the ADT Installer script or
|
||||
through a build directory that is based on your metadata
|
||||
through a Yocto Project build tree that is based on your metadata
|
||||
configuration or extension for your targeted device.
|
||||
The cross-toolchain works with a matching target sysroot.
|
||||
</para>
|
||||
@@ -68,38 +63,11 @@
|
||||
The matching target sysroot contains needed headers and libraries for generating
|
||||
binaries that run on the target architecture.
|
||||
The sysroot is based on the target root filesystem image that is built by
|
||||
the OpenEmbedded build system Poky and uses the same metadata configuration
|
||||
the Yocto Project's build system Poky and uses the same metadata configuration
|
||||
used to build the cross-toolchain.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='eclipse-overview'>
|
||||
<title>Eclipse Yocto Plug-in</title>
|
||||
|
||||
<para>
|
||||
The Eclipse IDE is a popular development environment and it fully supports
|
||||
development using the Yocto Project.
|
||||
When you install and configure the Eclipse Yocto Project Plug-in into
|
||||
the Eclipse IDE, you maximize your Yocto Project experience.
|
||||
Installing and configuring the Plug-in results in an environment that
|
||||
has extensions specifically designed to let you more easily develop software.
|
||||
These extensions allow for cross-compilation, deployment, and execution of
|
||||
your output into a QEMU emulation session.
|
||||
You can also perform cross-debugging and profiling.
|
||||
The environment also supports a suite of tools that allows you to perform
|
||||
remote profiling, tracing, collection of power data, collection of
|
||||
latency data, and collection of performance data.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For information about the application development workflow that uses the Eclipse
|
||||
IDE and for a detailed example of how to install and configure the Eclipse
|
||||
Yocto Project Plug-in, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#adt-eclipse'>Working Within Eclipse</ulink>" section
|
||||
of the Yocto Project Development Manual.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='the-qemu-emulator'>
|
||||
<title>The QEMU Emulator</title>
|
||||
|
||||
@@ -111,8 +79,8 @@
|
||||
<listitem><para>If you use the ADT Installer script to install ADT, you can
|
||||
specify whether or not to install QEMU.</para></listitem>
|
||||
<listitem><para>If you have downloaded a Yocto Project release and unpacked
|
||||
it to create a source directory and you have sourced
|
||||
the environment setup script, QEMU is installed and automatically
|
||||
it to create a Yocto Project file structure and you have sourced
|
||||
the Yocto Project environment setup script, QEMU is installed and automatically
|
||||
available.</para></listitem>
|
||||
<listitem><para>If you have installed the cross-toolchain
|
||||
tarball and you have sourcing the toolchain's setup environment script, QEMU
|
||||
@@ -152,7 +120,7 @@
|
||||
<listitem><para><emphasis>SystemTap:</emphasis> A free software infrastructure
|
||||
that simplifies information gathering about a running Linux system.
|
||||
This information helps you diagnose performance or functional problems.
|
||||
SystemTap is not available as a user-space tool through the Eclipse IDE Yocto Plug-in.
|
||||
SystemTap is not available as a user-space tool through the Yocto Eclipse IDE Plug-in.
|
||||
See <ulink url='http://sourceware.org/systemtap'></ulink> for more information
|
||||
on SystemTap.</para></listitem>
|
||||
<listitem><para><emphasis>Lttng-ust:</emphasis> A User-space Tracer designed to
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<book id='adt-manual' lang='en'
|
||||
<book id='adt-manual' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/adt-title.png'
|
||||
format='SVG'
|
||||
<imagedata fileref='figures/adt-title.png'
|
||||
format='SVG'
|
||||
align='left' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title></title>
|
||||
@@ -50,9 +50,14 @@
|
||||
<revremark>Released with the Yocto Project 1.2 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
<revnumber>1.2.1</revnumber>
|
||||
<date>July 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.2.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.2.2</revnumber>
|
||||
<date>January 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.2.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
@@ -63,14 +68,15 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
under the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as
|
||||
published by Creative Commons.
|
||||
</para>
|
||||
<note>
|
||||
Due to production processes, there could be differences between the Yocto Project
|
||||
documentation bundled in the release tarball and the
|
||||
documentation bundled in the release tarball and the
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>
|
||||
Yocto Project Application Developer's Guide</ulink> on
|
||||
Application Developer's Toolkit (ADT) User's Guide</ulink> on
|
||||
the <ulink url='&YOCTO_HOME_URL;'>Yocto Project</ulink> website.
|
||||
For the latest version of this manual, see the manual on the website.
|
||||
</note>
|
||||
@@ -85,6 +91,8 @@
|
||||
|
||||
<xi:include href="adt-package.xml"/>
|
||||
|
||||
<xi:include href="adt-eclipse.xml"/>
|
||||
|
||||
<xi:include href="adt-command.xml"/>
|
||||
|
||||
<!-- <index id='index'>
|
||||
@@ -93,6 +101,6 @@
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<title>Package Management Systems</title>
|
||||
|
||||
<para>
|
||||
The OpenEmbedded build system supports the generation of sysroot files using
|
||||
The Yocto Project supports the generation of sysroot files using
|
||||
three different Package Management Systems (PMS):
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>OPKG:</emphasis> A less well known PMS whose use
|
||||
@@ -28,7 +28,7 @@
|
||||
<listitem><para><emphasis>RPM:</emphasis> A more widely known PMS intended for GNU/Linux
|
||||
distributions.
|
||||
This PMS works with files packaged in an <filename>.rms</filename> format.
|
||||
The build system currently installs through this PMS by default.
|
||||
The Yocto Project currently installs through this PMS by default.
|
||||
See <ulink url='http://en.wikipedia.org/wiki/RPM_Package_Manager'></ulink>
|
||||
for more information about RPM.</para></listitem>
|
||||
<listitem><para><emphasis>Debian:</emphasis> The PMS for Debian-based systems
|
||||
@@ -45,8 +45,7 @@
|
||||
|
||||
<para>
|
||||
Whichever PMS you are using, you need to be sure that the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-PACKAGE_CLASSES'><filename>PACKAGE_CLASSES</filename></ulink>
|
||||
variable in the <filename>conf/local.conf</filename>
|
||||
<filename>PACKAGE_CLASSES</filename> variable in the <filename>conf/local.conf</filename>
|
||||
file is set to reflect that system.
|
||||
The first value you choose for the variable specifies the package file format for the root
|
||||
filesystem at sysroot.
|
||||
@@ -56,8 +55,7 @@
|
||||
|
||||
<note>
|
||||
For build performance information related to the PMS, see
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#ref-classes-package'>Packaging - <filename>package*.bbclass</filename></ulink>
|
||||
in the Yocto Project Reference Manual.
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#ref-classes-package'>Packaging - <filename>package*.bbclass</filename></ulink> in The Yocto Project Reference Manual.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
@@ -77,8 +75,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, source the environment setup script found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
Next, source the environment setup script found in the Yocto Project files.
|
||||
Follow that by setting up the installation destination to point to your
|
||||
sysroot as <filename><sysroot_dir></filename>.
|
||||
Finally, have an OPKG configuration file <filename><conf_file></filename>
|
||||
|
||||
@@ -4,41 +4,25 @@
|
||||
|
||||
<chapter id='adt-prepare'>
|
||||
|
||||
<title>Preparing for Application Development</title>
|
||||
<title>Preparing to Use the Application Development Toolkit (ADT)</title>
|
||||
|
||||
<para>
|
||||
In order to develop applications, you need set up your host development system.
|
||||
Several ways exist that allow you to install cross-development tools, QEMU, the
|
||||
Eclipse Yocto Plug-in, and other tools.
|
||||
This chapter describes how to prepare for application development.
|
||||
In order to use the ADT, you must install it, <filename>source</filename> a script to set up the
|
||||
environment, and be sure both the kernel and filesystem image specific to the target architecture
|
||||
exist.
|
||||
This chapter describes how to be sure you meet the ADT requirements.
|
||||
</para>
|
||||
|
||||
<section id='installing-the-adt'>
|
||||
<title>Installing the ADT and Toolchains</title>
|
||||
<title>Installing the ADT</title>
|
||||
|
||||
<para>
|
||||
The following list describes installation methods that set up varying degrees of tool
|
||||
availabiltiy on your system.
|
||||
Regardless of the installation method you choose,
|
||||
you must <filename>source</filename> the cross-toolchain
|
||||
environment setup script before you use a toolchain.
|
||||
The following list describes how you can install the ADT, which includes the cross-toolchain.
|
||||
Regardless of the installation you choose, you must <filename>source</filename> the cross-toolchain
|
||||
environment setup script before you use the toolchain.
|
||||
See the "<link linkend='setting-up-the-cross-development-environment'>Setting Up the
|
||||
Cross-Development Environment</link>" section for more information.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>Avoid mixing installation methods when installing toolchains for different architectures.
|
||||
For example, avoid using the ADT Installer to install some toolchains and then hand-installing
|
||||
cross-development toolchains from downloaded tarballs to install toolchains
|
||||
for different architectures.
|
||||
Mixing installation methods can result in situations where the ADT Installer becomes
|
||||
unreliable and might not install the toolchain.</para>
|
||||
<para>If you must mix installation methods, you might avoid problems by deleting
|
||||
<filename>/var/lib/opkg</filename>, thus purging the <filename>opkg</filename> package
|
||||
metadata</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Cross-Development Environment</link>"
|
||||
section for more information.
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Use the ADT Installer Script:</emphasis>
|
||||
This method is the recommended way to install the ADT because it
|
||||
@@ -51,10 +35,9 @@
|
||||
toolchain tarball and then hand-install the toolchain.
|
||||
If you use this method, you just get the cross-toolchain and QEMU - you do not
|
||||
get any of the other mentioned benefits had you run the ADT Installer script.</para></listitem>
|
||||
<listitem><para><emphasis>Use the Toolchain from within the Build Directory:</emphasis>
|
||||
If you already have a
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>,
|
||||
you can build the cross-toolchain within the directory.
|
||||
<listitem><para><emphasis>Use the Toolchain from within a Yocto Project Build Tree:</emphasis>
|
||||
If you already have a Yocto Project build tree, you can build the cross-toolchain
|
||||
within tree.
|
||||
However, like the previous method mentioned, you only get the cross-toolchain and QEMU - you
|
||||
do not get any of the other benefits without taking separate steps.</para></listitem>
|
||||
</itemizedlist>
|
||||
@@ -77,22 +60,22 @@
|
||||
<ulink url='&YOCTO_DL_URL;/releases'>Index of Releases</ulink>, specifically
|
||||
at
|
||||
<ulink url='&YOCTO_ADTINSTALLER_DL_URL;'></ulink>.
|
||||
Or, you can use BitBake to generate the tarball inside the existing
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
Or, you can use BitBake to generate the tarball inside the existing Yocto Project
|
||||
build tree.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you use BitBake to generate the ADT Installer tarball, you must
|
||||
<filename>source</filename> the environment setup script
|
||||
<filename>source</filename> the Yocto Project environment setup script
|
||||
(<filename>oe-init-build-env</filename>) located
|
||||
in the source directory before running the <filename>bitbake</filename>
|
||||
in the Yocto Project file structure before running the <filename>bitbake</filename>
|
||||
command that creates the tarball.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following example commands download the Poky tarball, set up the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>,
|
||||
set up the environment while also creating the default build directory,
|
||||
The following example commands download the Yocto Project release tarball, set up the Yocto
|
||||
Project files structure, set up the environment while also creating the
|
||||
default Yocto Project build tree,
|
||||
and run the <filename>bitbake</filename> command that results in the tarball
|
||||
<filename>~/yocto-project/build/tmp/deploy/sdk/adt_installer.tar.bz2</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -153,7 +136,7 @@
|
||||
or not to install the emulator QEMU.</para></listitem>
|
||||
<listitem><para><filename>YOCTOADT_NFS_UTIL</filename>: Indicates whether
|
||||
or not to install user-mode NFS.
|
||||
If you plan to use the Eclipse IDE Yocto plug-in against QEMU,
|
||||
If you plan to use the Yocto Eclipse IDE plug-in against QEMU,
|
||||
you should install NFS.
|
||||
<note>To boot QEMU images using our userspace NFS server, you need
|
||||
to be running <filename>portmap</filename> or <filename>rpcbind</filename>.
|
||||
@@ -183,10 +166,7 @@
|
||||
|
||||
<para>
|
||||
After you have configured the <filename>adt_installer.conf</filename> file,
|
||||
run the installer using the following command.
|
||||
Be sure that you are not trying to use cross-compilation tools.
|
||||
When you run the installer, the environment must use a
|
||||
host <filename>gcc</filename>:
|
||||
run the installer using the following command:
|
||||
<literallayout class='monospaced'>
|
||||
$ ./adt_installer
|
||||
</literallayout>
|
||||
@@ -246,17 +226,17 @@
|
||||
poky-eglibc-x86_64-i586-toolchain-gmae-&DISTRO;.tar.bz2
|
||||
</literallayout>
|
||||
<note><para>As an alternative to steps one and two, you can build the toolchain tarball
|
||||
if you have a <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
if you have a Yocto Project build tree.
|
||||
If you need GMAE, you should use the <filename>bitbake meta-toolchain-gmae</filename>
|
||||
command.
|
||||
The resulting tarball will support such development.
|
||||
However, if you are not concerned with GMAE,
|
||||
you can generate the tarball using <filename>bitbake meta-toolchain</filename>.</para>
|
||||
<para>Use the appropriate <filename>bitbake</filename> command only after you have
|
||||
sourced the <filename>oe-build-init-env</filename> script located in the source
|
||||
directory.
|
||||
sourced the <filename>oe-build-init-env</filename> script located in the Yocto
|
||||
Project files.
|
||||
When the <filename>bitbake</filename> command completes, the tarball will
|
||||
be in <filename>tmp/deploy/sdk</filename> in the build directory.
|
||||
be in <filename>tmp/deploy/sdk</filename> in the Yocto Project build tree.
|
||||
</para></note></para></listitem>
|
||||
<listitem><para>Make sure you are in the root directory with root privileges and then expand
|
||||
the tarball.
|
||||
@@ -269,49 +249,46 @@
|
||||
</section>
|
||||
|
||||
<section id='using-the-toolchain-from-within-the-build-tree'>
|
||||
<title>Using BitBake and the Build Directory</title>
|
||||
<title>Using BitBake and the Yocto Project Build Tree</title>
|
||||
|
||||
<para>
|
||||
A final way of making the cross-toolchain available is to use BitBake
|
||||
to generate the toolchain within an existing
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
This method does not install the toolchain into the
|
||||
<filename>/opt</filename> directory.
|
||||
A final way of installing just the cross-toolchain is to use BitBake to build the
|
||||
toolchain within an existing Yocto Project build tree.
|
||||
This method does not install the toolchain into the <filename>/opt</filename> directory.
|
||||
As with the previous method, if you need to install the target sysroot, you must
|
||||
do that separately as well.
|
||||
do this separately.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Follow these steps to generate the toolchain into the build directory:
|
||||
Follow these steps to build and install the toolchain into the build tree:
|
||||
<orderedlist>
|
||||
<listitem><para>Source the environment setup script
|
||||
<filename>oe-init-build-env</filename> located in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
</para></listitem>
|
||||
<filename>oe-init-build-env</filename> located in the Yocto Project
|
||||
files.</para></listitem>
|
||||
<listitem><para>At this point, you should be sure that the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-MACHINE'><filename>MACHINE</filename></ulink> variable
|
||||
<filename>MACHINE</filename> variable
|
||||
in the <filename>local.conf</filename> file found in the
|
||||
<filename>conf</filename> directory of the build directory
|
||||
<filename>conf</filename> directory of the Yocto Project build directory
|
||||
is set for the target architecture.
|
||||
Comments within the <filename>local.conf</filename> file list the values you
|
||||
can use for the <filename>MACHINE</filename> variable.
|
||||
<note>You can populate the build directory with the cross-toolchains for more
|
||||
<note>You can populate the build tree with the cross-toolchains for more
|
||||
than a single architecture.
|
||||
You just need to edit the <filename>MACHINE</filename> variable in the
|
||||
<filename>local.conf</filename> file and re-run the BitBake
|
||||
command.</note></para></listitem>
|
||||
<listitem><para>Run <filename>bitbake meta-ide-support</filename> to complete the
|
||||
cross-toolchain generation.
|
||||
<note>If you change out of your working directory after you
|
||||
cross-toolchain installation.
|
||||
<note>If change out of your working directory after you
|
||||
<filename>source</filename> the environment setup script and before you run
|
||||
the <filename>bitbake</filename> command, the command might not work.
|
||||
Be sure to run the <filename>bitbake</filename> command immediately
|
||||
after checking or editing the <filename>local.conf</filename> but without
|
||||
changing out of your working directory.</note>
|
||||
Once the <filename>bitbake</filename> command finishes,
|
||||
the cross-toolchain is generated and populated within the build directory.
|
||||
the tarball for the cross-toolchain is generated within the Yocto Project build tree.
|
||||
You will notice environment setup files for the cross-toolchain in the
|
||||
build directory in the <filename>tmp</filename> directory.
|
||||
Yocto Project build tree in the <filename>tmp</filename> directory.
|
||||
Setup script filenames contain the strings <filename>environment-setup</filename>.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
@@ -325,13 +302,11 @@
|
||||
<para>
|
||||
Before you can develop using the cross-toolchain, you need to set up the
|
||||
cross-development environment by sourcing the toolchain's environment setup script.
|
||||
If you used the ADT Installer or hand-installed cross-toolchain,
|
||||
If you used the ADT Installer or used an existing ADT tarball to install the ADT,
|
||||
then you can find this script in the <filename>&YOCTO_ADTPATH_DIR;</filename>
|
||||
directory.
|
||||
If you installed the toolchain in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>,
|
||||
you can find the environment setup
|
||||
script for the toolchain in the build directory's <filename>tmp</filename> directory.
|
||||
If you installed the toolchain in the build tree, you can find the environment setup
|
||||
script for the toolchain in the Yocto Project build tree's <filename>tmp</filename> directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -365,21 +340,20 @@
|
||||
pre-built versions.
|
||||
You can find examples for both these situations in the
|
||||
"<ulink url='&YOCTO_DOCS_QS_URL;#test-run'>A Quick Test Run</ulink>" section of
|
||||
the Yocto Project Quick Start.
|
||||
The Yocto Project Quick Start.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Yocto Project ships basic kernel and filesystem images for several
|
||||
The Yocto Project provides basic kernel and filesystem images for several
|
||||
architectures (<filename>x86</filename>, <filename>x86-64</filename>,
|
||||
<filename>mips</filename>, <filename>powerpc</filename>, and <filename>arm</filename>)
|
||||
that you can use unaltered in the QEMU emulator.
|
||||
These kernel images reside in the release
|
||||
These kernel images reside in the Yocto Project release
|
||||
area - <ulink url='&YOCTO_MACHINES_DL_URL;'></ulink>
|
||||
and are ideal for experimentation using Yocto Project.
|
||||
For information on the image types you can build using the OpenEmbedded build system,
|
||||
see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Images</ulink>" chapter in
|
||||
the Yocto Project Reference Manual.
|
||||
and are ideal for experimentation within Yocto Project.
|
||||
For information on the image types you can build using the Yocto Project, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Reference: Images</ulink>" appendix in
|
||||
The Yocto Project Reference Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -396,10 +370,8 @@
|
||||
you can do so one of two ways:
|
||||
<itemizedlist>
|
||||
<listitem><para>Modify the <filename>conf/local.conf</filename> configuration in
|
||||
the <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
and then rebuild the image.
|
||||
With this method, you need to modify the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-EXTRA_IMAGE_FEATURES'><filename>EXTRA_IMAGE_FEATURES</filename></ulink>
|
||||
the Yocto Project build directory and then rebuild the image.
|
||||
With this method, you need to modify the <filename>EXTRA_IMAGE_FEATURES</filename>
|
||||
variable to have the value of "tools-debug" before rebuilding the image.
|
||||
Once the image is rebuilt, the <filename>tcf-agent</filename> will be included
|
||||
in the image and is launched automatically after the boot.</para></listitem>
|
||||
@@ -407,7 +379,7 @@
|
||||
To build the agent, follow these steps:
|
||||
<orderedlist>
|
||||
<listitem><para>Be sure the ADT is installed as described in the
|
||||
"<link linkend='installing-the-adt'>Installing the ADT and Toolchains</link>" section.
|
||||
"<link linkend='installing-the-adt'>Installing the ADT</link>" section.
|
||||
</para></listitem>
|
||||
<listitem><para>Set up the cross-development environment as described in the
|
||||
"<link linkend='setting-up-the-cross-development-environment'>Setting
|
||||
@@ -420,8 +392,7 @@
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Modify the <filename>Makefile.inc</filename> file
|
||||
for the cross-compilation environment by setting the
|
||||
<filename>OPSYS</filename> and
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-MACHINE'><filename>MACHINE</filename></ulink>
|
||||
<filename>OPSYS</filename> and <filename>MACHINE</filename>
|
||||
variables according to your target.</para></listitem>
|
||||
<listitem><para>Use the cross-development tools to build the
|
||||
<filename>tcf-agent</filename>.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
@@ -110,7 +110,7 @@ h5 {
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<book id='bsp-guide' lang='en'
|
||||
<book id='bsp-guide' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/bsp-title.png'
|
||||
format='SVG'
|
||||
<imagedata fileref='figures/bsp-title.png'
|
||||
format='SVG'
|
||||
align='center' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title></title>
|
||||
<title></title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
@@ -62,9 +62,14 @@
|
||||
<revremark>Released with the Yocto Project 1.2 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
<revnumber>1.2.1</revnumber>
|
||||
<date>July 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.2.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.2.2</revnumber>
|
||||
<date>January 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.2.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
@@ -75,12 +80,13 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-nc-sa/2.0/uk/">Creative Commons Attribution-Non-Commercial-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-nc-sa/2.0/uk/">Creative Commons Attribution-Non-Commercial-Share Alike 2.0 UK: England & Wales</ulink> as
|
||||
published by Creative Commons.
|
||||
</para>
|
||||
<note>
|
||||
Due to production processes, there could be differences between the Yocto Project
|
||||
documentation bundled in the release tarball and the
|
||||
documentation bundled in the release tarball and the
|
||||
<ulink url='&YOCTO_DOCS_BSP_URL;'>
|
||||
Board Support Package (BSP) Developer's Guide</ulink> on
|
||||
the <ulink url='&YOCTO_HOME_URL;'>Yocto Project</ulink> website.
|
||||
@@ -98,6 +104,6 @@
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -48,8 +48,8 @@
|
||||
This root is what you add to the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-BBLAYERS'><filename>BBLAYERS</filename></ulink>
|
||||
variable in the <filename>conf/bblayers.conf</filename> file found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
Adding the root allows the OpenEmbedded build system to recognize the BSP
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>Yocto Project Build Directory</ulink>.
|
||||
Adding the root allows the Yocto Project build system to recognize the BSP
|
||||
definition and from it build an image.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -99,14 +99,13 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The proposed form does have elements that are specific to the
|
||||
OpenEmbedded build system.
|
||||
The proposed form does have elements that are specific to the Yocto Project and
|
||||
OpenEmbedded build systems.
|
||||
It is intended that this information can be
|
||||
used by other build systems besides the OpenEmbedded build system
|
||||
and that it will be simple
|
||||
used by other systems besides Yocto Project and OpenEmbedded and that it will be simple
|
||||
to extract information and convert it to other formats if required.
|
||||
The OpenEmbedded build system, through its standard layers mechanism, can directly
|
||||
accept the format described as a layer.
|
||||
Yocto Project, through its standard layers mechanism, can directly accept the format
|
||||
described as a layer.
|
||||
The BSP captures all
|
||||
the hardware-specific details in one place in a standard format, which is
|
||||
useful for any person wishing to use the hardware platform regardless of
|
||||
@@ -298,10 +297,9 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>conf/layer.conf</filename> file identifies the file structure as a
|
||||
layer, identifies the
|
||||
contents of the layer, and contains information about how the build
|
||||
system should use it.
|
||||
The <filename>conf/layer.conf</filename> file identifies the file structure as a Yocto
|
||||
Project layer, identifies the
|
||||
contents of the layer, and contains information about how Yocto Project should use it.
|
||||
Generally, a standard boilerplate file such as the following works.
|
||||
In the following example, you would replace "<filename>bsp</filename>" and
|
||||
"<filename>_bsp</filename>" with the actual name
|
||||
@@ -314,8 +312,8 @@
|
||||
BBPATH := "${BBPATH}:${LAYERDIR}"
|
||||
|
||||
# We have a recipes directory, add to BBFILES
|
||||
BBFILES := "${BBFILES} ${LAYERDIR}/recipes-*/*.bb \
|
||||
${LAYERDIR}/recipes-*/*.bbappend"
|
||||
BBFILES := "${BBFILES} ${LAYERDIR}/recipes/*/*.bb \
|
||||
${LAYERDIR}/recipes/*/*.bbappend"
|
||||
|
||||
BBFILE_COLLECTIONS += "bsp"
|
||||
BBFILE_PATTERN_bsp := "^${LAYERDIR}/"
|
||||
@@ -335,7 +333,7 @@
|
||||
|
||||
<para>
|
||||
This file simply makes BitBake aware of the recipes and configuration directories.
|
||||
The file must exist so that the OpenEmbedded build system can recognize the BSP.
|
||||
The file must exist so that the Yocto Project build system can recognize the BSP.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -350,7 +348,7 @@
|
||||
|
||||
<para>
|
||||
The machine files bind together all the information contained elsewhere
|
||||
in the BSP into a format that the build system can understand.
|
||||
in the BSP into a format that the Yocto Project build system can understand.
|
||||
If the BSP supports multiple machines, multiple machine configuration files
|
||||
can be present.
|
||||
These filenames correspond to the values to which users have set the
|
||||
@@ -390,8 +388,8 @@
|
||||
|
||||
<para>
|
||||
Tuning files are found in the <filename>meta/conf/machine/include</filename>
|
||||
directory within the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
directory of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto Project Files</ulink>.
|
||||
Tuning files can also reside in the BSP Layer itself.
|
||||
For example, the <filename>ia32-base.inc</filename> file resides in the
|
||||
<filename>meta-intel</filename> BSP Layer in <filename>conf/machine/include</filename>.
|
||||
@@ -443,7 +441,7 @@
|
||||
formfactor recipe
|
||||
<filename>meta/recipes-bsp/formfactor/formfactor_0.0.bb</filename>,
|
||||
which is found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto Project Files</ulink>.
|
||||
</para></note>
|
||||
</section>
|
||||
|
||||
@@ -505,33 +503,33 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
These files append your specific changes to the main kernel recipe you are using.
|
||||
These files append your specific changes to the kernel you are using.
|
||||
</para>
|
||||
<para>
|
||||
For your BSP, you typically want to use an existing Yocto Project kernel recipe found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>
|
||||
at <filename>meta/recipes-kernel/linux</filename>.
|
||||
For your BSP, you typically want to use an existing Yocto Project kernel found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto
|
||||
Project Files</ulink> at <filename>meta/recipes-kernel/linux</filename>.
|
||||
You can append your specific changes to the kernel recipe by using a
|
||||
similarly named append file, which is located in the BSP Layer (e.g.
|
||||
the <filename>meta-<bsp_name>/recipes-kernel/linux</filename> directory).
|
||||
</para>
|
||||
<para>
|
||||
Suppose you are using the <filename>linux-yocto_3.4.bb</filename> recipe to build
|
||||
the kernel.
|
||||
Suppose the BSP uses the <filename>linux-yocto_3.0.bb</filename> kernel,
|
||||
which is the preferred kernel to use for developing a new BSP using the Yocto Project.
|
||||
In other words, you have selected the kernel in your
|
||||
<filename><bsp_name>.conf</filename> file by adding the following statements:
|
||||
<literallayout class='monospaced'>
|
||||
PREFERRED_PROVIDER_virtual/kernel ?= "linux-yocto"
|
||||
PREFERRED_VERSION_linux-yocto = "3.4%"
|
||||
PREFERRED_VERSION_linux-yocto = "3.0%"
|
||||
</literallayout>
|
||||
You would use the <filename>linux-yocto_3.4.bbappend</filename> file to append
|
||||
You would use the <filename>linux-yocto_3.0.bbappend</filename> file to append
|
||||
specific BSP settings to the kernel, thus configuring the kernel for your particular BSP.
|
||||
</para>
|
||||
<para>
|
||||
As an example, look at the existing Crown Bay BSP.
|
||||
The append file used is:
|
||||
<literallayout class='monospaced'>
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_3.4.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_3.0.bbappend
|
||||
</literallayout>
|
||||
The following listing shows the file.
|
||||
Be aware that the actual commit ID strings in this example listing might be different
|
||||
@@ -541,87 +539,82 @@
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
COMPATIBLE_MACHINE_crownbay = "crownbay"
|
||||
KMACHINE_crownbay = "crownbay"
|
||||
KBRANCH_crownbay = "standard/default/crownbay"
|
||||
KMACHINE_crownbay = "yocto/standard/crownbay"
|
||||
KERNEL_FEATURES_append_crownbay += " cfg/smp.scc"
|
||||
|
||||
COMPATIBLE_MACHINE_crownbay-noemgd = "crownbay-noemgd"
|
||||
KMACHINE_crownbay-noemgd = "crownbay"
|
||||
KBRANCH_crownbay-noemgd = "standard/default/crownbay"
|
||||
KMACHINE_crownbay-noemgd = "yocto/standard/crownbay"
|
||||
KERNEL_FEATURES_append_crownbay-noemgd += " cfg/smp.scc"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "48101e609711fcfe8d5e737a37a5a69f4bd57d9a"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "5b4c9dc78b5ae607173cc3ddab9bce1b5f78129b"
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "63c65842a3a74e4bd3128004ac29b5639f16433f"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "59314a3523e360796419d76d78c6f7d8c5ef2593"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay-noemgd ?= "48101e609711fcfe8d5e737a37a5a69f4bd57d9a"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay-noemgd ?= "5b4c9dc78b5ae607173cc3ddab9bce1b5f78129b"
|
||||
SRCREV_machine_pn-linux-yocto_crownbay-noemgd ?= "63c65842a3a74e4bd3128004ac29b5639f16433f"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay-noemgd ?= "59314a3523e360796419d76d78c6f7d8c5ef2593"
|
||||
</literallayout>
|
||||
This append file contains statements used to support the Crown Bay BSP for both
|
||||
<trademark class='registered'>Intel</trademark> EMGD and the VESA graphics.
|
||||
The build process, in this case, recognizes and uses only the statements that
|
||||
apply to the defined machine name - <filename>crownbay</filename> in this case.
|
||||
So, the applicable statements in the <filename>linux-yocto_3.4.bbappend</filename>
|
||||
So, the applicable statements in the <filename>linux-yocto_3.0.bbappend</filename>
|
||||
file are follows:
|
||||
<literallayout class='monospaced'>
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
COMPATIBLE_MACHINE_crownbay = "crownbay"
|
||||
KMACHINE_crownbay = "crownbay"
|
||||
KBRANCH_crownbay = "standard/default/crownbay"
|
||||
KMACHINE_crownbay = "yocto/standard/crownbay"
|
||||
KERNEL_FEATURES_append_crownbay += " cfg/smp.scc"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "48101e609711fcfe8d5e737a37a5a69f4bd57d9a"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "5b4c9dc78b5ae607173cc3ddab9bce1b5f78129b"
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "63c65842a3a74e4bd3128004ac29b5639f16433f"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "59314a3523e360796419d76d78c6f7d8c5ef2593"
|
||||
</literallayout>
|
||||
The append file defines <filename>crownbay</filename> as the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-COMPATIBLE_MACHINE'><filename>COMPATIBLE_MACHINE</filename></ulink>
|
||||
and uses the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-KMACHINE'><filename>KMACHINE</filename></ulink> variable to
|
||||
ensure the machine name used by the OpenEmbedded build system maps to the
|
||||
machine name used by the Linux Yocto kernel.
|
||||
The file also uses the optional
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-KBRANCH'><filename>KBRANCH</filename></ulink> variable
|
||||
to ensure the build process uses the <filename>standard/default/crownbay</filename>
|
||||
kernel branch.
|
||||
Finally, the append file points to the specific top commits in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink> Git
|
||||
The append file defines <filename>crownbay</filename> as the compatible machine and
|
||||
defines the <filename>KMACHINE</filename>.
|
||||
The file also points to some configuration fragments to use by setting the
|
||||
<filename>KERNEL_FEATURES</filename> variable.
|
||||
The location for the configuration fragments is the kernel tree itself in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>Yocto Project Build
|
||||
Directory</ulink> under <filename>linux/meta</filename>.
|
||||
Finally, the append file points to the specific commits in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto Project Files</ulink> Git
|
||||
repository and the <filename>meta</filename> Git repository branches to identify the
|
||||
exact kernel needed to build the Crown Bay BSP.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
One thing missing in this particular BSP, which you will typically need when
|
||||
developing a BSP, is the kernel configuration file (<filename>.config</filename>) for your BSP.
|
||||
When developing a BSP, you probably have a kernel configuration file or a set of kernel
|
||||
configuration files that, when taken together, define the kernel configuration for your BSP.
|
||||
You can accomplish this definition by putting the configurations in a file or a set of files
|
||||
inside a directory located at the same level as your kernel's append file and having the same
|
||||
name as the kernel's main recipe file.
|
||||
With all these conditions met, simply reference those files in a
|
||||
inside a directory located at the same level as your append file and having the same name
|
||||
as the kernel.
|
||||
With all these conditions met simply reference those files in a
|
||||
<filename>SRC_URI</filename> statement in the append file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For example, suppose you had a some configuration options in a file called
|
||||
<filename>network_configs.cfg</filename>.
|
||||
You can place that file inside a directory named <filename>/linux-yocto</filename> and then add
|
||||
a <filename>SRC_URI</filename> statement such as the following to the append file.
|
||||
When the OpenEmbedded build system builds the kernel, the configuration options are
|
||||
picked up and applied.
|
||||
For example, suppose you had a set of configuration options in a file called
|
||||
<filename>myconfig</filename>.
|
||||
If you put that file inside a directory named
|
||||
<filename>/linux-yocto</filename> and then added
|
||||
a <filename>SRC_URI</filename> statement such as the following to the append file,
|
||||
those configuration
|
||||
options will be picked up and applied when the kernel is built.
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI += "file://network_configs.cfg"
|
||||
SRC_URI += "file://myconfig"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To group related configurations into multiple files, you perform a similar procedure.
|
||||
Here is an example that groups separate configurations specifically for Ethernet and graphics
|
||||
into their own files and adds the configurations
|
||||
by using a <filename>SRC_URI</filename> statement like the following in your append file:
|
||||
As mentioned earlier, you can group related configurations into multiple files and
|
||||
name them all in the <filename>SRC_URI</filename> statement as well.
|
||||
For example, you could group separate configurations specifically for Ethernet and graphics
|
||||
into their own files and add those by using a <filename>SRC_URI</filename> statement like the
|
||||
following in your append file:
|
||||
<literallayout class='monospaced'>
|
||||
SRC_URI += "file://myconfig.cfg \
|
||||
SRC_URI += "file://myconfig \
|
||||
file://eth.cfg \
|
||||
file://gfx.cfg"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>FILESEXTRAPATHS</filename> variable is in boilerplate form in the
|
||||
previous example in order to make it easy to do that.
|
||||
@@ -630,36 +623,32 @@
|
||||
The <filename>FILESEXTRAPATHS</filename> variable enables the build process to
|
||||
find those configuration files.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Other methods exist to accomplish grouping and defining configuration options.
|
||||
For example, if you are working with a local clone of the kernel repository,
|
||||
you could checkout the kernel's <filename>meta</filename> branch, make your changes,
|
||||
and then push the changes to the local bare clone of the kernel.
|
||||
The result is that you directly add configuration options to the
|
||||
<filename>meta</filename> branch for your BSP.
|
||||
The configuration options will likely end up in that location anyway if the BSP gets
|
||||
added to the Yocto Project.
|
||||
For an example showing how to change the BSP configuration, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#changing-the-bsp-configuration'>Changing the BSP Configuration</ulink>"
|
||||
section in the Yocto Project Development Manual.
|
||||
For a better understanding of working with a local clone of the kernel repository
|
||||
and a local bare clone of the kernel, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#modifying-the-kernel-source-code'>Modifying the Kernel
|
||||
Source Code</ulink>" section also in the Yocto Project Development Manual.
|
||||
</para>
|
||||
|
||||
Other methods exist to accomplish grouping and defining configuration options.
|
||||
For example, if you are working with a local clone of the kernel repository,
|
||||
you could checkout the kernel's <filename>meta</filename> branch, make your changes,
|
||||
and then push the changes to the local bare clone of the kernel.
|
||||
The result is that you directly add configuration options to the Yocto kernel
|
||||
<filename>meta</filename> branch for your BSP.
|
||||
The configuration options will likely end up in that location anyway if the BSP gets
|
||||
added to the Yocto Project.
|
||||
For an example showing how to change the BSP configuration, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#changing-the-bsp-configuration'>Changing the BSP Configuration</ulink>"
|
||||
section in the Yocto Project Development Manual.
|
||||
For a better understanding of working with a local clone of the kernel repository
|
||||
and a local bare clone of the kernel, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#modifying-the-kernel-source-code'>Modifying the Kernel
|
||||
Source Code</ulink>" section also in the Yocto Project Development Manual.</para>
|
||||
<para>
|
||||
In general, however, the Yocto Project maintainers take care of moving the
|
||||
<filename>SRC_URI</filename>-specified
|
||||
configuration options to the kernel's <filename>meta</filename> branch.
|
||||
Not only is it easier for BSP developers to not have to worry about putting those
|
||||
configurations in the branch, but having the maintainers do it allows them to apply
|
||||
'global' knowledge about the kinds of common configuration options multiple BSPs in
|
||||
the tree are typically using.
|
||||
This allows for promotion of common configurations into common features.
|
||||
</para>
|
||||
In general, however, the Yocto Project maintainers take care of moving the
|
||||
<filename>SRC_URI</filename>-specified
|
||||
configuration options to the kernel's <filename>meta</filename> branch.
|
||||
Not only is it easier for BSP developers to not have to worry about putting those
|
||||
configurations in the branch, but having the maintainers do it allows them to apply
|
||||
'global' knowledge about the kinds of common configuration options multiple BSPs in
|
||||
the tree are typically using.
|
||||
This allows for promotion of common configurations into common features.</para>
|
||||
</note>
|
||||
</section>
|
||||
</section>
|
||||
@@ -683,7 +672,7 @@
|
||||
<itemizedlist>
|
||||
<listitem><para>The requirements here assume the BSP layer is a well-formed, "legal"
|
||||
layer that can be added to the Yocto Project.
|
||||
For guidelines on creating a layer that meets these base requirements, see the
|
||||
For guidelines on creating a Yocto Project layer that meets these base requirements, see the
|
||||
"<link linkend='bsp-layers'>BSP Layers</link>" and the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#understanding-and-creating-layers'>Understanding
|
||||
and Creating Layers"</ulink> in the Yocto Project Development Manual.</para></listitem>
|
||||
@@ -730,15 +719,15 @@
|
||||
<filename>recipe-*</filename> subdirectory.
|
||||
You can find <filename>recipes.txt</filename> in the
|
||||
<filename>meta</filename> directory of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>,
|
||||
or in the OpenEmbedded Core Layer
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto
|
||||
Project Files</ulink>, or in the OpenEmbedded Core Layer
|
||||
(<filename>openembedded-core</filename>) found at
|
||||
<ulink url='http://git.openembedded.org/openembedded-core/tree/meta'></ulink>.
|
||||
</para>
|
||||
<para>Within any particular <filename>recipes-*</filename> category, the layout
|
||||
should match what is found in the OpenEmbedded Core
|
||||
Git repository (<filename>openembedded-core</filename>)
|
||||
or the source directory (<filename>poky</filename>).
|
||||
or the Yocto Project Files (<filename>poky</filename>).
|
||||
In other words, make sure you place related files in appropriately
|
||||
related <filename>recipes-*</filename> subdirectories specific to the
|
||||
recipe's function, or within a subdirectory containing a set of closely-related
|
||||
@@ -921,7 +910,7 @@
|
||||
for a component or components.
|
||||
For these cases, you are required to accept the terms of a commercial or other
|
||||
type of license that requires some kind of explicit End User License Agreement (EULA).
|
||||
Once the license is accepted, the OpenEmbedded build system can then build and
|
||||
Once the license is accepted, the Yocto Project build system can then build and
|
||||
include the corresponding component in the final BSP image.
|
||||
If the BSP is available as a pre-built image, you can download the image after
|
||||
agreeing to the license or EULA.
|
||||
@@ -964,12 +953,13 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A couple different methods exist within the OpenEmbedded build system to
|
||||
satisfy the licensing requirements for an encumbered BSP.
|
||||
A couple different methods exist within the Yocto
|
||||
Project build system to satisfy the licensing
|
||||
requirements for an encumbered BSP.
|
||||
The following list describes them in order of preference:
|
||||
<orderedlist>
|
||||
<listitem><para><emphasis>Use the <filename>LICENSE_FLAGS</filename> variable
|
||||
to define the recipes that have commercial or other types of
|
||||
to define the Yocto Project recipes that have commercial or other types of
|
||||
specially-licensed packages:</emphasis>
|
||||
For each of those recipes, you can
|
||||
specify a matching license string in a
|
||||
@@ -1034,7 +1024,7 @@
|
||||
The Yocto Project includes a couple of tools that enable
|
||||
you to create a <link linkend='bsp-layers'>BSP layer</link>
|
||||
from scratch and do basic configuration and maintenance
|
||||
of the kernel without ever looking at a metadata file.
|
||||
of the kernel without ever looking at a Yocto Project metadata file.
|
||||
These tools are <filename>yocto-bsp</filename> and <filename>yocto-kernel</filename>,
|
||||
respectively.
|
||||
</para>
|
||||
@@ -1061,7 +1051,8 @@
|
||||
|
||||
<para>
|
||||
Both tools reside in the <filename>scripts/</filename> subdirectory
|
||||
of the <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
of the <ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto Project
|
||||
Files</ulink>.
|
||||
Consequently, to use the scripts, you must <filename>source</filename> the
|
||||
environment just as you would when invoking a build:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -1113,7 +1104,7 @@
|
||||
[-i <JSON PROPERTY FILE> | --infile <JSON PROPERTY_FILE>]
|
||||
|
||||
This command creates a Yocto BSP based on the specified parameters.
|
||||
The new BSP will be a new BSP layer contained by default within
|
||||
The new BSP will be a new Yocto BSP layer contained by default within
|
||||
the top-level directory specified as 'meta-bsp-name'. The -o option
|
||||
can be used to place the BSP layer in a directory with a different
|
||||
name and location.
|
||||
@@ -1319,8 +1310,8 @@
|
||||
<listitem><para>The remainder of the prompts are routine.
|
||||
Defaults are accepted for each.</para></listitem>
|
||||
<listitem><para>By default, the script creates the new BSP Layer in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
</para></listitem>
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>Yocto Project
|
||||
Build Directory</ulink>.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
@@ -1345,7 +1336,8 @@
|
||||
<title>Managing Kernel Patches and Config Items with yocto-kernel</title>
|
||||
|
||||
<para>
|
||||
Assuming you have created a <link linkend='bsp-layers'>BSP Layer</link> using
|
||||
Assuming you have created a Yocto Project
|
||||
<link linkend='bsp-layers'>BSP Layer</link> using
|
||||
<link linkend='creating-a-new-bsp-layer-using-the-yocto-bsp-script'>
|
||||
<filename>yocto-bsp</filename></link> and you added it to your
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-BBLAYERS'><filename>BBLAYERS</filename></ulink>
|
||||
@@ -1356,7 +1348,7 @@
|
||||
|
||||
<para>
|
||||
The <filename>yocto-kernel</filename> script allows you to add, remove, and list patches
|
||||
and kernel config settings to a BSP's kernel
|
||||
and kernel config settings to a Yocto Project BSP's kernel
|
||||
<filename>.bbappend</filename> file.
|
||||
All you need to do is use the appropriate sub-command.
|
||||
Recall that the easiest way to see exactly what sub-commands are available
|
||||
|
||||
@@ -110,7 +110,7 @@ h5 {
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,20 +23,19 @@
|
||||
</para>
|
||||
|
||||
<section id='getting-local-yocto-project-files-and-bsp-files'>
|
||||
<title>Getting Local Source Files and BSP Files</title>
|
||||
<title>Getting Local Yocto Project Files and BSP Files</title>
|
||||
|
||||
<para>
|
||||
You need to have the <link linkend='source-directory'>source directory</link>
|
||||
available on your host system.
|
||||
You can set up this directory through tarball extraction or by cloning the
|
||||
<filename>poky</filename> Git repository.
|
||||
You need to have the Yocto Project files available on your host system.
|
||||
You can get files through tarball extraction or by cloning the <filename>poky</filename>
|
||||
Git repository.
|
||||
The following paragraphs describe both methods.
|
||||
For additional information, see the bulleted item
|
||||
"<link linkend='local-yp-release'>Yocto Project Release</link>".
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As mentioned, one way to set up the source directory is to use Git to clone the
|
||||
As mentioned, one way to get the Yocto Project files is to use Git to clone the
|
||||
<filename>poky</filename> repository.
|
||||
These commands create a local copy of the Git repository.
|
||||
By default, the top-level directory of the repository is named <filename>poky</filename>:
|
||||
@@ -45,8 +44,8 @@
|
||||
$ cd poky
|
||||
</literallayout>
|
||||
Alternatively, you can start with the downloaded Poky "&DISTRO_NAME;" tarball.
|
||||
These commands unpack the tarball into a source directory structure.
|
||||
By default, the top-level directory of the source directory is named
|
||||
These commands unpack the tarball into a Yocto Project File directory structure.
|
||||
By default, the top-level directory of the file structure is named
|
||||
<filename>&YOCTO_POKY;</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ tar xfj &YOCTO_POKY_TARBALL;
|
||||
@@ -61,7 +60,8 @@
|
||||
|
||||
<para>Once you expand the released tarball, you have a snapshot of the Git repository
|
||||
that represents a specific release.
|
||||
Fundamentally, this is different than having a local copy of the Poky Git repository.
|
||||
Fundamentally, this is different than having a local copy of the Yocto Project
|
||||
Git repository.
|
||||
Given the tarball method, changes you make are building on top of a release.
|
||||
With the Git repository method you have the ability to track development
|
||||
and keep changes in revision control.
|
||||
@@ -133,12 +133,12 @@
|
||||
|
||||
<para>
|
||||
You need to have the base BSP layer on your development system.
|
||||
Similar to the local <link linkend='source-directory'>source directory</link>,
|
||||
Similar to the local <link linkend='yocto-project-files'>Yocto Project Files</link>,
|
||||
you can get the BSP
|
||||
layer in a couple of different ways:
|
||||
download the BSP tarball and extract it, or set up a local Git repository that
|
||||
has the BSP layers.
|
||||
You should use the same method that you used to set up the source directory earlier.
|
||||
has the Yocto Project BSP layers.
|
||||
You should use the same method that you used to get the local Yocto Project files earlier.
|
||||
See "<link linkend='getting-setup'>Getting Setup</link>" for information on how to get
|
||||
the BSP files.
|
||||
</para>
|
||||
@@ -196,8 +196,8 @@
|
||||
<title>Making a Copy of the Base BSP to Create Your New BSP Layer</title>
|
||||
|
||||
<para>
|
||||
Now that you have set up the source directory and included the base BSP files, you need to
|
||||
create a new layer for your BSP.
|
||||
Now that you have the local Yocto Project files and the base BSP files, you need to create a
|
||||
new layer for your BSP.
|
||||
To create your BSP layer, you simply copy the <filename>meta-crownbay</filename>
|
||||
layer to a new layer.
|
||||
</para>
|
||||
@@ -207,7 +207,7 @@
|
||||
The name should follow the BSP layer naming convention, which is
|
||||
<filename>meta-<name></filename>.
|
||||
The following assumes your working directory is <filename>meta-intel</filename>
|
||||
inside your source directory.
|
||||
inside the local Yocto Project files.
|
||||
To start your new layer, just copy the new layer alongside the existing
|
||||
BSP layers in the <filename>meta-intel</filename> directory:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -239,7 +239,7 @@
|
||||
First, since in this example the new BSP will not support EMGD, we will get rid of the
|
||||
<filename>crownbay.conf</filename> file and then rename the
|
||||
<filename>crownbay-noemgd.conf</filename> file to <filename>mymachine.conf</filename>.
|
||||
Much of what we do in the configuration directory is designed to help the OpenEmbedded
|
||||
Much of what we do in the configuration directory is designed to help the Yocto Project
|
||||
build system work with the new layer and to be able to find and use the right software.
|
||||
The following two commands result in a single machine configuration file named
|
||||
<filename>mymachine.conf</filename>.
|
||||
@@ -266,7 +266,7 @@
|
||||
<filename>PREFERRED_VERSION_linux-yocto</filename> statement.
|
||||
This statement identifies the kernel that the BSP is going to use.
|
||||
In this case, the BSP is using <filename>linux-yocto</filename>, which is the
|
||||
current Yocto Project kernel based on the Linux 3.2 release.
|
||||
current Linux Yocto kernel based on the Linux 3.2 release.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -312,7 +312,7 @@
|
||||
When you create a BSP, you use these areas for appropriate recipes and append files.
|
||||
Recipes take the form of <filename>.bb</filename> files, while append files take
|
||||
the form of <filename>.bbappend</filename> files.
|
||||
If you want to leverage the existing recipes the OpenEmbedded build system uses
|
||||
If you want to leverage the existing recipes the Yocto Project build system uses
|
||||
but change those recipes, you can use <filename>.bbappend</filename> files.
|
||||
All new recipes and append files for your layer must go in the layer’s
|
||||
<filename>recipes-bsp</filename>, <filename>recipes-kernel</filename>,
|
||||
@@ -365,7 +365,7 @@
|
||||
Now let's look at changes in <filename>recipes-core</filename>.
|
||||
The file <filename>task-core-tools.bbappend</filename> in
|
||||
<filename>recipes-core/tasks</filename> appends the similarly named recipe
|
||||
located in the <link linkend='source-directory'>source directory</link> at
|
||||
located in the local <link linkend='yocto-project-files'>Yocto Project Files</link> at
|
||||
<filename>meta/recipes-core/tasks</filename>.
|
||||
The append file in our layer right now is Crown Bay-specific and supports
|
||||
EMGD and non-EMGD.
|
||||
@@ -395,7 +395,7 @@
|
||||
Recall that the BSP uses the <filename>linux-yocto</filename> kernel as determined
|
||||
earlier in the <filename>mymachine.conf</filename>.
|
||||
The recipe for that kernel is not located in the
|
||||
BSP layer but rather in the source directory at
|
||||
BSP layer but rather in the local Yocto Project files at
|
||||
<filename>meta/recipes-kernel/linux</filename> and is
|
||||
named <filename>linux-yocto_3.2.bb</filename>.
|
||||
The <filename>SRCREV_machine</filename> and <filename>SRCREV_meta</filename>
|
||||
@@ -515,10 +515,8 @@
|
||||
|
||||
<para>
|
||||
Also in the <filename>linux-yocto_3.2.bbappend</filename> file are
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-COMPATIBLE_MACHINE'><filename>COMPATIBLE_MACHINE</filename></ulink>,
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-KMACHINE'><filename>KMACHINE</filename></ulink>,
|
||||
and
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-KBRANCH'><filename>KBRANCH</filename></ulink> statements.
|
||||
<filename>COMPATIBLE_MACHINE</filename>, <filename>KMACHINE</filename>,
|
||||
and <filename>KBRANCH</filename> statements.
|
||||
Two sets of these exist: one set supports EMGD and one set does not.
|
||||
Because we are not interested in supporting EMGD those three can be deleted.
|
||||
The remaining three must be changed so that <filename>mymachine</filename> replaces
|
||||
@@ -578,14 +576,15 @@
|
||||
<orderedlist>
|
||||
<listitem><para>Get the environment ready for the build by sourcing the environment
|
||||
script.
|
||||
The environment script is in the top-level of the source directory.
|
||||
The environment script is in the top-level of the local Yocto Project files
|
||||
directory structure.
|
||||
The script has the string
|
||||
<filename>init-build-env</filename> in the file’s name.
|
||||
For this example, the following command gets the build environment ready:
|
||||
<literallayout class='monospaced'>
|
||||
$ source oe-init-build-env yocto-build
|
||||
</literallayout>
|
||||
When you source the script, a build directory is created in the current
|
||||
When you source the script a build directory is created in the current
|
||||
working directory.
|
||||
In our example we were in the <filename>poky</filename> directory.
|
||||
Thus, entering the previous command created the <filename>yocto-build</filename> directory.
|
||||
@@ -622,9 +621,10 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#ref-variables-glos'>Variables Glossary</ulink> chapter in the
|
||||
Yocto Project Reference Manual has more information on configuration variables.
|
||||
The appendix
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#ref-variables-glos'>
|
||||
Reference: Variables Glossary</ulink> in the Yocto Project Reference Manual has more information
|
||||
on configuration variables.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,13 +18,12 @@
|
||||
sources where you can find more detail.
|
||||
For example, detailed information on Git, repositories and open source in general
|
||||
can be found in many places.
|
||||
Another example is how to get set up to use the Yocto Project, which our Yocto Project
|
||||
Quick Start covers.
|
||||
Another example is how to get set up to use the Yocto Project, which our Yocto Project Quick Start covers.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Yocto Project Development Manual, however, does provide detailed examples on how to create a
|
||||
Board Support Package (BSP), change the kernel source code, and reconfigure the kernel.
|
||||
Board Support Package (BSP), change the kernel source code, and re-configure the kernel.
|
||||
You can find this information in the appendices of the manual.
|
||||
</para>
|
||||
</section>
|
||||
@@ -45,7 +44,13 @@
|
||||
applications.</para></listitem>
|
||||
<listitem><para>An overview and understanding of the emulation environment used with
|
||||
the Yocto Project (QEMU).</para></listitem>
|
||||
<listitem><para>An understanding of basic kernel architecture and concepts.</para></listitem>
|
||||
<!-- <listitem><para>A discussion of target-level analysis techniques, tools, tips,
|
||||
and tricks.</para></listitem>
|
||||
<listitem><para>Considerations for deploying your final product.</para></listitem> -->
|
||||
<listitem><para>An understanding of basic kernel architecture and
|
||||
concepts.</para></listitem>
|
||||
<!-- <listitem><para>Information that will help you migrate an existing project to the
|
||||
Yocto Project development environment.</para></listitem> -->
|
||||
<listitem><para>Many references to other sources of related information.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
@@ -59,7 +64,7 @@
|
||||
<itemizedlist>
|
||||
<listitem><para>Step-by-step instructions if those instructions exist in other Yocto
|
||||
Project documentation.
|
||||
For example, the Yocto Project Development Manual contains detailed
|
||||
For example, the Application Development Toolkit (ADT) User’s Guide contains detailed
|
||||
instruction on how to obtain and configure the
|
||||
<trademark class='trade'>Eclipse</trademark> Yocto Plug-in.</para></listitem>
|
||||
<listitem><para>Reference material.
|
||||
@@ -92,14 +97,13 @@
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;'>
|
||||
The Yocto Project Reference Manual</ulink>:</emphasis> This manual is a reference
|
||||
guide to the OpenEmbedded build system known as "Poky."
|
||||
guide to the Yocto Project build component known as "Poky."
|
||||
The manual also contains a reference chapter on Board Support Package (BSP)
|
||||
layout.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>
|
||||
The Yocto Project Application Developer's Guide</ulink>:</emphasis>
|
||||
This guide provides information that lets you get going with the Application
|
||||
Development Toolkit (ADT) and stand-alone cross-development toolchains to
|
||||
The Yocto Project Application Development Toolkit (ADT) User's Guide</ulink>:</emphasis>
|
||||
This guide provides information that lets you get going with the ADT to
|
||||
develop projects using the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_BSP_URL;'>
|
||||
@@ -113,7 +117,7 @@
|
||||
some work flow examples.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='http://www.youtube.com/watch?v=3ZlOu-gLsh0'>
|
||||
Eclipse IDE Yocto Plug-in</ulink>:</emphasis> A step-by-step instructional video that
|
||||
Yocto Eclipse Plug-in</ulink>:</emphasis> A step-by-step instructional video that
|
||||
demonstrates how an application developer uses Yocto Plug-in features within
|
||||
the Eclipse IDE.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
@@ -129,11 +133,8 @@
|
||||
Hob's primary goal is to enable a user to perform common tasks more easily.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_HOME_URL;/documentation/build-appliance'>
|
||||
Build Appliance</ulink>:</emphasis> A bootable custom embedded Linux image you can
|
||||
either build using a non-Linux development system (VMware applications) or download
|
||||
from the Yocto Project website.
|
||||
See the <ulink url='&YOCTO_HOME_URL;/documentation/build-appliance'>Build Appliance</ulink>
|
||||
page for more information.</para></listitem>
|
||||
Build Appliance</ulink>:</emphasis> Allows you to build and boot a custom embedded Linux
|
||||
image with the Yocto Project using a non-Linux development system.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_BUGZILLA_URL;'>Bugzilla</ulink>:</emphasis>
|
||||
The bug tracking application the Yocto Project uses.
|
||||
@@ -148,34 +149,30 @@
|
||||
<listitem><para><ulink url='&YOCTO_LISTS_URL;/listinfo/poky'></ulink> for a
|
||||
Yocto Project Discussions mailing list about the Poky build system.</para></listitem>
|
||||
<listitem><para><ulink url='&YOCTO_LISTS_URL;/listinfo/yocto-announce'></ulink>
|
||||
for a mailing list to receive official Yocto Project announcements for developments and
|
||||
for a mailing list to receive offical Yocto Project announcements for developments and
|
||||
as well as Yocto Project milestones.</para></listitem>
|
||||
</itemizedlist></para></listitem>
|
||||
<listitem><para><emphasis>Internet Relay Chat (IRC):</emphasis>
|
||||
Two IRC channels on freenode are available
|
||||
for Yocto Project and Poky discussions: <filename>#yocto</filename> and
|
||||
<filename>#poky</filename>, respectively.</para></listitem>
|
||||
<filename>#poky</filename>.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&OH_HOME_URL;'>OpenedHand</ulink>:</emphasis>
|
||||
The company that initially developed the Poky project, which is the basis
|
||||
for the OpenEmbedded build system used by the Yocto Project.
|
||||
OpenedHand was acquired by Intel Corporation in 2008.</para></listitem>
|
||||
The company where the Yocto Project build system Poky was first developed.
|
||||
OpenedHand has since been acquired by Intel Corporation.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='http://www.intel.com/'>Intel Corporation</ulink>:</emphasis>
|
||||
A multinational semiconductor chip manufacturer company whose Software and
|
||||
Services Group created and supports the Yocto Project.
|
||||
Intel acquired OpenedHand in 2008.</para></listitem>
|
||||
The company that acquired OpenedHand in 2008 and continues development on the
|
||||
Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&OE_HOME_URL;'>OpenEmbedded</ulink>:</emphasis>
|
||||
The build system used by the Yocto Project.
|
||||
This project is the upstream, generic, embedded distribution from which the Yocto
|
||||
Project derives its build system (Poky) from and to which it contributes.</para></listitem>
|
||||
The upstream, generic, embedded distribution the Yocto Project build system (Poky) derives
|
||||
from and to which it contributes.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='http://developer.berlios.de/projects/bitbake/'>
|
||||
BitBake</ulink>:</emphasis> The tool used by the OpenEmbedded build system
|
||||
to process project metadata.</para></listitem>
|
||||
BitBake</ulink>:</emphasis> The tool used to process Yocto Project metadata.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&BITBAKE_DOCS_URL;'>
|
||||
<ulink url='http://bitbake.berlios.de/manual/'>
|
||||
BitBake User Manual</ulink>:</emphasis> A comprehensive guide to the BitBake tool.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
|
||||
@@ -12,6 +12,17 @@
|
||||
or even altering the source code itself.
|
||||
This appendix presents simple examples that modify the kernel source code,
|
||||
change the kernel configuration, and add a kernel source recipe.
|
||||
<!-- [WRITER'S NOTE: I might want to work in information about applying a local
|
||||
change to a kernel layer and also pushing a change upstream into the tree]
|
||||
<orderedlist>
|
||||
<listitem><para>Iteratively determine and set kernel configurations and make
|
||||
kernel recipe changes.</para></listitem>
|
||||
<listitem><para>Apply your configuration changes to your local kernel layer.
|
||||
</para></listitem>
|
||||
<listitem><para>Push your configuration and recipe changes upstream into the
|
||||
Yocto Project source repositories to make them available to the community.
|
||||
</para></listitem>
|
||||
</orderedlist> -->
|
||||
</para>
|
||||
|
||||
<section id='modifying-the-kernel-source-code'>
|
||||
@@ -34,17 +45,18 @@
|
||||
Briefly, you need the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>A local
|
||||
<link linkend='source-directory'>source directory</link> for the
|
||||
poky Git repository</para></listitem>
|
||||
<listitem><para>Local copies of the
|
||||
<link linkend='yocto-project-files'>Yocto Project Files</link>
|
||||
Git repository</para></listitem>
|
||||
<listitem><para>The
|
||||
<link linkend='poky-extras-repo'><filename>poky-extras</filename></link>
|
||||
Git repository placed within the source directory.</para></listitem>
|
||||
Git repository placed within the local Yocto Project files Git
|
||||
repository</para></listitem>
|
||||
<listitem><para>A bare clone of the
|
||||
<link linkend='local-kernel-files'>Yocto Project Kernel</link> upstream Git
|
||||
<link linkend='local-kernel-files'>Linux Yocto Kernel</link> upstream Git
|
||||
repository to which you want to push your modifications.
|
||||
</para></listitem>
|
||||
<listitem><para>A copy of that bare clone in which you make your source
|
||||
modifications</para></listitem>
|
||||
modifcations</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@@ -66,31 +78,30 @@
|
||||
<para>
|
||||
Here is a brief description of the four areas:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Local Source Directory:</emphasis>
|
||||
This area contains all the metadata that supports building images
|
||||
using the OpenEmbedded build system.
|
||||
In this example, the source directory also
|
||||
<listitem><para><emphasis>Local Yocto Project Files Git Repository:</emphasis>
|
||||
This area contains all the metadata that supports building images in the
|
||||
Yocto Project build environment - the local Yocto Project files.
|
||||
In this example, the local Yocto Project files Git repository also
|
||||
contains the build directory, which contains the configuration directory
|
||||
that lets you control the build.
|
||||
Also in this example, the source directory contains local copies of the
|
||||
In this example, the repository also contains the
|
||||
<filename>poky-extras</filename> Git repository.</para>
|
||||
<para>See the bulleted item
|
||||
"<link linkend='local-yp-release'>Yocto Project Release</link>"
|
||||
for information on how to get these files on your local system.</para></listitem>
|
||||
<listitem><para><emphasis>Local copies of the<filename>poky-extras</filename>
|
||||
Git Repository:</emphasis>
|
||||
for information on how to get these files.</para></listitem>
|
||||
<listitem><para><emphasis><filename>poky-extras</filename> Git Repository:</emphasis>
|
||||
This area contains the <filename>meta-kernel-dev</filename> layer,
|
||||
which is where you make changes that append the kernel build recipes.
|
||||
You edit <filename>.bbappend</filename> files to locate your
|
||||
local kernel source files and to identify the kernel being built.
|
||||
This Git repository is a gathering place for extensions to the Yocto Project
|
||||
This Git repository is a gathering place for extensions to the Linux Yocto
|
||||
(or really any) kernel recipes that faciliate the creation and development
|
||||
of kernel features, BSPs or configurations.</para>
|
||||
<para>See the bulleted item
|
||||
"<link linkend='poky-extras-repo'>The
|
||||
<filename>poky-extras</filename> Git Repository</link>"
|
||||
for information on how to get these files.</para></listitem>
|
||||
<listitem><para><emphasis>Bare Clone of the Yocto Project kernel:</emphasis>
|
||||
<listitem><para><emphasis>Bare Clone of the Linux Yocto kernel:</emphasis>
|
||||
This bare Git repository tracks the upstream Git repository of the Linux
|
||||
Yocto kernel source code you are changing.
|
||||
When you modify the kernel you must work through a bare clone.
|
||||
@@ -100,15 +111,15 @@
|
||||
<filename>poky-extras</filename> repository points to the bare clone
|
||||
so that the build process can locate the locally changed source files.</para>
|
||||
<para>See the bulleted item
|
||||
"<link linkend='local-kernel-files'>Yocto Project Kernel</link>"
|
||||
"<link linkend='local-kernel-files'>Linux Yocto Kernel</link>"
|
||||
for information on how to set up the bare clone.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Copy of the Yocto Project Kernel Bare Clone:</emphasis>
|
||||
<listitem><para><emphasis>Copy of the Linux Yocto Kernel Bare Clone:</emphasis>
|
||||
This Git repository contains the actual source files that you modify.
|
||||
Any changes you make to files in this location need to ultimately be pushed
|
||||
to the bare clone using the <filename>git push</filename> command.</para>
|
||||
<para>See the bulleted item
|
||||
"<link linkend='local-kernel-files'>Yocto Project Kernel</link>"
|
||||
"<link linkend='local-kernel-files'>Linux Yocto Kernel</link>"
|
||||
for information on how to set up the bare clone.
|
||||
<note>Typically, Git workflows follow a scheme where changes made to a local area
|
||||
are pulled into a Git repository.
|
||||
@@ -122,23 +133,23 @@
|
||||
</section>
|
||||
|
||||
<section id='setting-up-the-local-yocto-project-files-git-repository'>
|
||||
<title>Setting Up the Local Source Directory</title>
|
||||
<title>Setting Up the Local Yocto Project Files Git Repository</title>
|
||||
|
||||
<para>
|
||||
You can set up the source directory through tarball extraction or by
|
||||
You can get the local Yocto Project files through tarball extraction or by
|
||||
cloning the <filename>poky</filename> Git repository.
|
||||
This example uses <filename>poky</filename> as the root directory of the
|
||||
local source directory.
|
||||
local Yocto Project files Git repository.
|
||||
See the bulleted item
|
||||
"<link linkend='local-yp-release'>Yocto Project Release</link>"
|
||||
for information on how to get these files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you have source directory set up,
|
||||
Once you have the repository set up,
|
||||
you have many development branches from which you can work.
|
||||
From inside the local repository you can see the branch names and the tag names used
|
||||
in the upstream Git repository by using either of the following commands:
|
||||
From inside the repository you can see the branch names and the tag names used
|
||||
in the Git repository using either of the following two commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd poky
|
||||
$ git branch -a
|
||||
@@ -157,15 +168,15 @@
|
||||
</section>
|
||||
|
||||
<section id='setting-up-the-poky-extras-git-repository'>
|
||||
<title>Setting Up the Local poky-extras Git Repository</title>
|
||||
<title>Setting Up the poky-extras Git Repository</title>
|
||||
|
||||
<para>
|
||||
This example creates a local copy of the <filename>poky-extras</filename> Git
|
||||
repository inside the <filename>poky</filename> source directory.
|
||||
See the bulleted item "<link linkend='poky-extras-repo'>The
|
||||
This example places the <filename>poky-extras</filename> Git repository inside
|
||||
of <filename>poky</filename>.
|
||||
See the bulleted item
|
||||
"<link linkend='poky-extras-repo'>The
|
||||
<filename>poky-extras</filename> Git Repository</link>"
|
||||
for information on how to set up a local copy of the
|
||||
<filename>poky-extras</filename> repository.
|
||||
for information on how to get the <filename>poky-extras</filename> repository.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -192,7 +203,7 @@
|
||||
Thus, you need to create a bare clone of that kernel and then make a copy of the
|
||||
bare clone.
|
||||
See the bulleted item
|
||||
"<link linkend='local-kernel-files'>Yocto Project Kernel</link>"
|
||||
"<link linkend='local-kernel-files'>Linux Yocto Kernel</link>"
|
||||
for information on how to do that.
|
||||
</para>
|
||||
|
||||
@@ -358,7 +369,7 @@
|
||||
<para>
|
||||
Once the source code has been modified, you need to use Git to push the changes to
|
||||
the bare clone.
|
||||
If you do not push the changes, then the OpenEmbedded build system will not pick
|
||||
If you do not push the changes, then the Yocto Project build system will not pick
|
||||
up the changed source files.
|
||||
</para>
|
||||
|
||||
@@ -375,7 +386,7 @@
|
||||
|
||||
<para>
|
||||
At this point, the source has been changed and pushed.
|
||||
The example now defines some variables used by the OpenEmbedded build system
|
||||
The example now defines some variables used by the Yocto Project build system
|
||||
to locate your kernel source.
|
||||
You essentially need to identify where to find the kernel recipe and the changed source code.
|
||||
You also need to be sure some basic configurations are in place that identify the
|
||||
@@ -436,23 +447,25 @@
|
||||
<literallayout class='monospaced'>
|
||||
KSRC_linux_yocto_3_2 ?= "/home/scottrif/linux-yocto-3.2.git"
|
||||
</literallayout></para></listitem>
|
||||
<!-- <listitem><para><emphasis>Specify the Kernel Machine:</emphasis> Also in the
|
||||
<filename>linux-yocto_3.2.bbappend</filename> file, you need to specify
|
||||
the kernel machine with the following statement:
|
||||
<literallayout class='monospaced'>
|
||||
KMACHINE_qemux86 = "standard/default/common-pc/base"
|
||||
</literallayout></para></listitem> -->
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>Before attempting to build the modified kernel, there is one more set of changes you
|
||||
Before attempting to build the modified kernel, there is one more set of changes you
|
||||
need to make in the <filename>meta-kernel-dev</filename> layer.
|
||||
Because all the kernel <filename>.bbappend</filename> files are parsed during the
|
||||
build process regardless of whether you are using them or not, you should either
|
||||
comment out the <filename>COMPATIBLE_MACHINE</filename> statements in all
|
||||
unused <filename>.bbappend</filename> files, or simply remove (or rename) all the files
|
||||
unused <filename>.bbappend</filename> files.
|
||||
Alternatively, you can simply remove all the files
|
||||
except the one your are using for the build
|
||||
(i.e. <filename>linux-yocto_3.2.bbappend</filename> in this example).</para>
|
||||
<para>If you do not make one of these two adjustments, your machine will be compatible
|
||||
with all the kernel recipes in the <filename>meta-kernel-dev</filename> layer.
|
||||
When your machine is comapatible with all the kernel recipes, the build attempts
|
||||
to build all kernels in the layer.
|
||||
You could end up with build errors blocking your work.</para>
|
||||
(i.e. <filename>linux-yocto_3.2.bbappend</filename> in this example).
|
||||
</note>
|
||||
</section>
|
||||
|
||||
@@ -477,7 +490,7 @@
|
||||
$ bitbake -c cleanall linux-yocto
|
||||
</literallayout></para>
|
||||
<para><note>Never remove any files by hand from the <filename>tmp/deploy</filename>
|
||||
directory insided the build directory.
|
||||
directory insided the local Yocto Project files build directory.
|
||||
Always use the BitBake <filename>cleanall</filename> task to clear
|
||||
out previous builds.</note></para></listitem>
|
||||
<listitem><para>Next, build the kernel image using this command:
|
||||
@@ -522,7 +535,7 @@
|
||||
<para>
|
||||
If you took the time to work through the example that modifies the kernel source code
|
||||
in "<link linkend='modifying-the-kernel-source-code'>Modifying the Kernel Source
|
||||
Code</link>" you should already have the source directory set up on your
|
||||
Code</link>" you should already have the Yocto Project files set up on your
|
||||
host machine.
|
||||
If this is the case, go to the next section, which is titled
|
||||
"<link linkend='examining-the-default-config-smp-behavior'>Examining the Default
|
||||
@@ -531,21 +544,21 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you don't have the source directory established on your system,
|
||||
If you don't have the Yocto Project files established on your system,
|
||||
you can get them through tarball extraction or by
|
||||
cloning the <filename>poky</filename> Git repository.
|
||||
This example uses <filename>poky</filename> as the root directory of the
|
||||
<link linkend='source-directory'>source directory</link>.
|
||||
local <link linkend='yocto-project-files'>Yocto Project Files</link> Git repository.
|
||||
See the bulleted item
|
||||
"<link linkend='local-yp-release'>Yocto Project Release</link>"
|
||||
for information on how to get these files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once you have the local copy of the repository set up,
|
||||
Once you have the repository set up,
|
||||
you have many development branches from which you can work.
|
||||
From inside the repository you can see the branch names and the tag names used
|
||||
in the upstream Git repository using either of the following commands:
|
||||
in the Git repository using either of the following two commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd poky
|
||||
$ git branch -a
|
||||
@@ -663,7 +676,7 @@
|
||||
to set kernel configurations.
|
||||
You need to run <filename>menuconfig</filename> inside the Yocto BitBake environment.
|
||||
Thus, the environment must be set up using the <filename>oe-init-build-env</filename>
|
||||
script found in the build directory.
|
||||
script found in the Yocto Project files Git repository build directory.
|
||||
If you have not sourced this script do so with the following commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
@@ -676,15 +689,23 @@
|
||||
to use the tool to interactively change the kernel configuration.
|
||||
In this example, we are basing our changes on the <filename>linux-yocto-3.2</filename>
|
||||
kernel.
|
||||
The OpenEmbedded build system recognizes this kernel as
|
||||
The Yocto Project build environment recognizes this kernel as
|
||||
<filename>linux-yocto</filename>.
|
||||
Thus, the following commands from the shell in which you previously sourced the
|
||||
environment initialization script cleans the shared state cache and the
|
||||
environment initialization script cleans the shared state memory and the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-WORKDIR'><filename>WORKDIR</filename></ulink>
|
||||
directory and then builds and launches <filename>menuconfig</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake linux-yocto -c cleansstate
|
||||
$ bitbake linux-yocto -c menuconfig
|
||||
</literallayout>
|
||||
<note>
|
||||
Due to a bug in the release, it is necessary to clean the shared state memory
|
||||
in order for configurations made using <filename>menuconfig</filename> to take
|
||||
effect.
|
||||
For information on the bug, see
|
||||
<ulink url='https://bugzilla.yoctoproject.org/show_bug.cgi?id=2256'></ulink>
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -700,9 +721,10 @@
|
||||
<para>
|
||||
Once you save the selection, the <filename>.config</filename> configuration file
|
||||
is updated.
|
||||
This is the file that the build system uses to configure the Yocto Project kernel
|
||||
This is the file that the build system uses to configure the Linux Yocto kernel
|
||||
when it is built.
|
||||
You can find and examine this file in the build directory.
|
||||
You can find and examine this file in the Yocto Project Files Git repository in
|
||||
the build directory.
|
||||
This example uses the following:
|
||||
<literallayout class='monospaced'>
|
||||
~/poky/build/tmp/work/qemux86-poky-linux/linux-yocto-3.2.11+git1+84f...
|
||||
@@ -736,7 +758,7 @@
|
||||
<note>
|
||||
Be sure to make a copy of the <filename>.config</filename> and don't just
|
||||
rename it.
|
||||
The build system needs an existing <filename>.config</filename>
|
||||
The Yocto Project build system needs an existing <filename>.config</filename>
|
||||
from which to work.
|
||||
</note>
|
||||
</para>
|
||||
@@ -747,11 +769,23 @@
|
||||
|
||||
<para>
|
||||
At this point, you are ready to recompile your kernel image with
|
||||
the new setting in effect using the BitBake command below:
|
||||
the new setting in effect using the BitBake commands below:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake linux-yocto -c compile -f
|
||||
$ bitbake linux-yocto
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
Manually turning off a kernel configuration setting such as
|
||||
<filename>CONFIG_SMP</filename> can cause the kernel configuration audit
|
||||
to issue warnings during the build.
|
||||
In this example, warnings appear telling you that the expected value
|
||||
<filename>CONFIG_SMP</filename> does not appear in the <filename>.config</filename>
|
||||
file.
|
||||
Because in this example you specifically turned off <filename>CONFIG_SMP</filename>,
|
||||
you can safely ignore the apparent conflict.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Now run the QEMU emulator and pass it the same multi-processor option as before:
|
||||
@@ -799,8 +833,352 @@
|
||||
width="2in" depth="3in" align="center" scalefit="1" />
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<!-- <section id='is-vfat-supported'>
|
||||
<title>Is VFAT Supported?</title>
|
||||
|
||||
<para>
|
||||
<literallayout class='monospaced'>
|
||||
I entered runqemu qemux86 and it fires upthis fires up the emulator and uses the
|
||||
image and filesystem in the build area created in the previous section.
|
||||
|
||||
Then I copied over a pre-created and formated 5.2MB VFAT file named vfat.img.
|
||||
I did this with scp vfat.img root@192.168.7.2:
|
||||
The file is in the root directory.
|
||||
I had to do this because the mkfs.vfat vfat.img command does not work.
|
||||
mkfs is not recognized in the qemu terminal session.
|
||||
|
||||
when I try mount -o loop -t vfat vfat.img mnt/ I get the error
|
||||
mount: can't set up loop device: No space left on device.
|
||||
This error is because the loop module is not currently in the kernel image.
|
||||
However, this module is available in the
|
||||
build area in the tarball modules-2.6.37.6-yocto-starndard+-20-qemux86.tgz.
|
||||
You can add this to the kernel image by adding the
|
||||
IMAGE_INSTALL += " kernel-module-loop" statement at the top of the local.conf
|
||||
file in the build area and then rebuilding the kernel using bitbake.
|
||||
It should just build whatever is necessary and not go through an entire build again.
|
||||
|
||||
|
||||
|
||||
|
||||
The <filename>menuconfig</filename> tool provides an interactive method with which
|
||||
to set kernel configurations.
|
||||
In order to use <filename>menuconfig</filename> from within the BitBake environment
|
||||
you need to source an environment setup script.
|
||||
This script is located in the local Yocto Project file structure and is called
|
||||
<filename>oe-init-build-env</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following command sets up the environment:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source oe-init-build-env
|
||||
$ runqemu qemux86
|
||||
Continuing with the following parameters:
|
||||
KERNEL: [/home/scottrif/poky/build/tmp/deploy/images/bzImage-qemux86.bin]
|
||||
ROOTFS: [/home/scottrif/poky/build/tmp/deploy/images/core-image-sato-qemux86.ext3]
|
||||
FSTYPE: [ext3]
|
||||
Setting up tap interface under sudo
|
||||
Acquiring lockfile for tap0...
|
||||
WARNING: distccd not present, no distcc support loaded.
|
||||
Running qemu...
|
||||
/home/scottrif/poky/build/tmp/sysroots/x86_64-linux/usr/bin/qemu
|
||||
-kernel /home/scottrif/poky/build/tmp/deploy/images/bzImage-qemux86.bin
|
||||
-net nic,vlan=0 -net tap,vlan=0,ifname=tap0,script=no,downscript=no
|
||||
-hda /home/scottrif/poky/build/tmp/deploy/images/core-image-sato-qemux86.ext3
|
||||
-show-cursor -usb -usbdevice wacom-tablet -vga vmware -enable-gl -no-reboot
|
||||
-m 128 ‐‐append "vga=0 root=/dev/hda rw mem=128M ip=192.168.7.2::192.168.7.1:255.255.255.0 oprofile.timer=1 "
|
||||
Enabling opengl
|
||||
vmsvga_value_write: guest runs Linux.
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='prepare-to-use-menuconfig'>
|
||||
<title>Prepare to use <filename>menuconfig</filename></title>
|
||||
|
||||
|
||||
<para>
|
||||
[WRITER'S NOTE: Stuff from here down are crib notes]
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once menuconfig fires up you see all kinds of categories that you can interactively
|
||||
investigate.
|
||||
If they have an "M" in it then the feature is "modularized".
|
||||
I guess that means that means that it needs to be manually linked in when the
|
||||
kernel is booted??? (Not sure).
|
||||
If they have an "*" then the feature is automatically part of the kernel.]
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So the tmp/work/ area was created in poky and there is a .config file in there and
|
||||
a .config.old file.
|
||||
The old one must have been created when I exited from menuconfig after poking around
|
||||
a bit.
|
||||
Nope - appears to just be created automatically.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A good practice is to first determine what configurations you have for the kernel.
|
||||
You can see the results by looking in the .config file in the build/tmp/work/qemux86-poky-linux area
|
||||
of the local YP files.
|
||||
There is a directory named linux-yocto-2.6.37* in the directory.
|
||||
In that directory is a directory named linux-qemux86-standard-build.
|
||||
In that directory you will find a file named .config that is the configuration file
|
||||
for the kernel that will be used when you build the kernel.
|
||||
You can open that file up and examine it.
|
||||
If you do a search for "VFAT" you will see that that particular configuration is not
|
||||
enabled for the kernel.
|
||||
This means that you cannot print a VFAT text file, or for that matter, even mount one
|
||||
from the image if you were to build it at this point.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can prove the point by actually trying it at this point.
|
||||
Here are the commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ mkdir ~/vfat-test
|
||||
$ cd ~/vfat-test
|
||||
$ dd if=/dev/zero of=vfat.img bs=1024 count=5000 [creates a 5MB disk image]
|
||||
5+0 records in
|
||||
5+0 records out
|
||||
5242880 bytes (5.2 MB) copied, 0.00798912 s, 656 MB/s
|
||||
$ ls -lah [lists the contents of the new image. l=long, a=all, h=human readable]
|
||||
total 5.1M
|
||||
drwxr-xr-x 2 srifenbark scottrif 4.0K 2011-08-01 08:18 .
|
||||
drwxr-xr-x 66 srifenbark scottrif 4.0K 2011-08-01 08:14 ..
|
||||
-rw-r‐‐r‐‐ 1 srifenbark scottrif 5.0M 2011-08-01 08:18 vfat.img
|
||||
$ mkfs.vfat vfat.img [formats the disk image]
|
||||
mkfs.vfat 3.0.7 (24 Dec 2009)
|
||||
$ mkdir mnt [mounts the disk image]
|
||||
$ sudo su [gives you root privilege]
|
||||
# mount -o loop vfat.img mnt [mounts it as a loop device]
|
||||
# ls mnt [shows nothing in mnt]
|
||||
# mount [lists the mounted filesystems - note/dev/loop0]
|
||||
/dev/sda1 on / type ext4 (rw,errors=remount-ro)
|
||||
proc on /proc type proc (rw,noexec,nosuid,nodev)
|
||||
none on /sys type sysfs (rw,noexec,nosuid,nodev)
|
||||
none on /sys/fs/fuse/connections type fusectl (rw)
|
||||
none on /sys/kernel/debug type debugfs (rw)
|
||||
none on /sys/kernel/security type securityfs (rw)
|
||||
none on /dev type devtmpfs (rw,mode=0755)
|
||||
none on /dev/pts type devpts (rw,noexec,nosuid,gid=5,mode=0620)
|
||||
none on /dev/shm type tmpfs (rw,nosuid,nodev)
|
||||
none on /var/run type tmpfs (rw,nosuid,mode=0755)
|
||||
none on /var/lock type tmpfs (rw,noexec,nosuid,nodev)
|
||||
none on /lib/init/rw type tmpfs (rw,nosuid,mode=0755)
|
||||
binfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,noexec,nosuid,nodev)
|
||||
gvfs-fuse-daemon on /home/scottrif/.gvfs type fuse.gvfs-fuse-daemon (rw,nosuid,nodev,user=srifenbark)
|
||||
/dev/loop0 on /home/scottrif/vfat-test/mnt type vfat (rw)
|
||||
# echo "hello world" > mnt/hello.txt [creates a text file in the mounted VFAT system]
|
||||
# ls mnt [verifies the file is there]
|
||||
hello.txt
|
||||
# cat mnt/hello.txt [displays the contents of the file created]
|
||||
hello world
|
||||
# umount mnt [unmounts the system and destroys the loop]
|
||||
# exit [gets out of privileged user mode]
|
||||
exit
|
||||
|
||||
$ lsmod [this stuff Darren did to show me ]
|
||||
Module Size Used by [the status of modules in the regular linux kernel]
|
||||
nls_iso8859_1 4633 0
|
||||
nls_cp437 6351 0
|
||||
vfat 10866 0
|
||||
fat 55350 1 vfat
|
||||
snd_hda_codec_atihdmi 3023 1
|
||||
binfmt_misc 7960 1
|
||||
snd_hda_codec_realtek 279008 1
|
||||
ppdev 6375 0
|
||||
snd_hda_intel 25805 2
|
||||
fbcon 39270 71
|
||||
tileblit 2487 1 fbcon
|
||||
font 8053 1 fbcon
|
||||
bitblit 5811 1 fbcon
|
||||
snd_hda_codec 85759 3 snd_hda_codec_atihdmi,snd_hda_codec_realtek,snd_hda_intel
|
||||
softcursor 1565 1 bitblit
|
||||
snd_seq_dummy 1782 0
|
||||
snd_hwdep 6924 1 snd_hda_codec
|
||||
vga16fb 12757 0
|
||||
snd_pcm_oss 41394 0
|
||||
snd_mixer_oss 16299 1 snd_pcm_oss
|
||||
snd_pcm 87946 3 snd_hda_intel,snd_hda_codec,snd_pcm_oss
|
||||
vgastate 9857 1 vga16fb
|
||||
snd_seq_oss 31191 0
|
||||
snd_seq_midi 5829 0
|
||||
snd_rawmidi 23420 1 snd_seq_midi
|
||||
radeon 744506 3
|
||||
snd_seq_midi_event 7267 2 snd_seq_oss,snd_seq_midi
|
||||
ttm 61007 1 radeon
|
||||
snd_seq 57481 6 snd_seq_dummy,snd_seq_oss,snd_seq_midi,snd_seq_midi_event
|
||||
drm_kms_helper 30742 1 radeon
|
||||
snd_timer 23649 2 snd_pcm,snd_seq
|
||||
snd_seq_device 6888 5 snd_seq_dummy,snd_seq_oss,snd_seq_midi,snd_rawmidi,snd_seq
|
||||
usb_storage 50377 0
|
||||
snd 71283 16 \
|
||||
snd_hda_codec_realtek,snd_hda_intel,snd_hda_codec, \
|
||||
snd_hwdep,snd_pcm_oss,snd_mixer_oss,snd_pcm, \
|
||||
snd_seq_oss,snd_rawmidi,snd_seq,snd_timer,snd_seq_device
|
||||
soundcore 8052 1 snd
|
||||
psmouse 65040 0
|
||||
drm 198886 5 radeon,ttm,drm_kms_helper
|
||||
i2c_algo_bit 6024 1 radeon
|
||||
serio_raw 4918 0
|
||||
snd_page_alloc 8500 2 snd_hda_intel,snd_pcm
|
||||
dell_wmi 2177 0
|
||||
dcdbas 6886 0
|
||||
lp 9336 0
|
||||
parport 37160 2 ppdev,lp
|
||||
usbhid 41116 0
|
||||
ohci1394 30260 0
|
||||
hid 83888 1 usbhid
|
||||
ieee1394 94771 1 ohci1394
|
||||
tg3 122382 0
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
</section> -->
|
||||
</appendix>
|
||||
|
||||
<!--
|
||||
|
||||
|
||||
EXTRA STUFF I MIGHT NEED BUT NOW SURE RIGHT NOW.
|
||||
|
||||
In the standard layer structure you have several areas that you need to examine or
|
||||
modify.
|
||||
For this example the layer contains four areas:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis><filename>conf</filename></emphasis> - Contains the
|
||||
<filename>layer.conf</filename> that identifies the location of the recipe files.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>images</filename></emphasis> - Contains the
|
||||
image recipe file.
|
||||
This recipe includes the base image you will be using and specifies other
|
||||
packages the image might need.</para></listitem>
|
||||
<listitem><para><emphasis><filename>recipes-bsp</filename></emphasis> - Contains
|
||||
recipes specific to the hardware for which you are developing the kernel.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>recipes-kernel</filename></emphasis> - Contains the
|
||||
"append" files that add information to the main recipe kernel.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Let's take a look at the <filename>layer.conf</filename> in the
|
||||
<filename>conf</filename> directory first.
|
||||
This configuration file enables the Yocto Project build system to locate and
|
||||
use the information in your new layer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The variable <filename>BBPATH</filename> needs to include the path to your layer
|
||||
as follows:
|
||||
<literallayout class='monospaced'>
|
||||
BBPATH := "${BBPATH}:${LAYERDIR}"
|
||||
</literallayout>
|
||||
And, the variable <filename>BBFILES</filename> needs to be modified to include your
|
||||
recipe and append files:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILES := "${BBFILES} ${LAYERDIR}/images/*.bb \
|
||||
${LAYERDIR}/images/*.bbappend \
|
||||
${LAYERDIR}/recipes-*/*/*.bb \
|
||||
${LAYERDIR}/recipes-*/*/*.bbappend"
|
||||
</literallayout>
|
||||
Finally, you need to be sure to use your layer name in these variables at the
|
||||
end of the file:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILE_COLLECTIONS += "elc"
|
||||
BBFILE_PATTERN_elc := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_elc = "9"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>images</filename> directory contains an append file that helps
|
||||
further define the image.
|
||||
In our example, the base image is <filename>core-image-minimal</filename>.
|
||||
The image does, however, need some additional modules that we are using
|
||||
for this example.
|
||||
These modules support the amixer functionality.
|
||||
Here is the append file:
|
||||
<literallayout class='monospaced'>
|
||||
require recipes-core/images/poky-image-minimal.bb
|
||||
|
||||
IMAGE_INSTALL += "dropbear alsa-utils-aplay alsa-utils-alsamixer"
|
||||
IMAGE_INSTALL_append_qemux86 += " kernel-module-snd-ens1370 \
|
||||
kernel-module-snd-rawmidi kernel-module-loop kernel-module-nls-cp437 \
|
||||
kernel-module-nls-iso8859-1 qemux86-audio alsa-utils-amixer"
|
||||
|
||||
LICENSE = "MIT"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
While the focus of this example is not on the BSP, it is worth mentioning that the
|
||||
<filename>recipes-bsp</filename> directory has the recipes and append files for
|
||||
features that the hardware requires.
|
||||
In this example, there is a script and a recipe to support the
|
||||
<filename>amixer</filename> functionality in QEMU.
|
||||
It is beyond the scope of this manual to go too deeply into the script.
|
||||
Suffice it to say that the script tests for the presence of the mixer, sets up
|
||||
default mixer values, enables the mixer, unmutes master and then
|
||||
sets the volume to 100.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The recipe <filename>qemu86-audio.bb</filename> installs and runs the
|
||||
<filename>amixer</filename> when the system boots.
|
||||
Here is the recipe:
|
||||
<literallayout class='monospaced'>
|
||||
SUMMARY = "Provide a basic init script to enable audio"
|
||||
DESCRIPTION = "Set the volume and unmute the Front mixer setting during boot."
|
||||
SECTION = "base"
|
||||
LICENSE = "MIT"
|
||||
LIC_FILES_CHKSUM = "file://${POKYBASE}/LICENSE;md5=3f40d7994397109285ec7b81fdeb3b58"
|
||||
|
||||
PR = "r4"
|
||||
|
||||
inherit update-rc.d
|
||||
|
||||
RDEPENDS = "alsa-utils-amixer"
|
||||
|
||||
SRC_URI = "file://qemux86-audio"
|
||||
|
||||
INITSCRIPT_NAME = "qemux86-audio"
|
||||
INITSCRIPT_PARAMS = "defaults 90"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${sysconfdir} \
|
||||
${D}${sysconfdir}/init.d
|
||||
install -m 0755 ${WORKDIR}/qemux86-audio ${D}${sysconfdir}/init.d
|
||||
cat ${WORKDIR}/${INITSCRIPT_NAME} | \
|
||||
sed -e 's,/etc,${sysconfdir},g' \
|
||||
-e 's,/usr/sbin,${sbindir},g' \
|
||||
-e 's,/var,${localstatedir},g' \
|
||||
-e 's,/usr/bin,${bindir},g' \
|
||||
-e 's,/usr,${prefix},g' > ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME}
|
||||
chmod 755 ${D}${sysconfdir}/init.d/${INITSCRIPT_NAME}
|
||||
}
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The last area to look at is <filename>recipes-kernel</filename>.
|
||||
This area holds configuration fragments and kernel append files.
|
||||
The append file must have the same name as the kernel recipe, which is
|
||||
<filename>linux-yocto-2.6.37</filename> in this example.
|
||||
The file can <filename>SRC_URI</filename> statements to point to configuration
|
||||
fragments you might have in the layer.
|
||||
The file can also contain <filename>KERNEL_FEATURES</filename> statements that specify
|
||||
included kernel configurations that ship with the Yocto Project.
|
||||
</para>
|
||||
-->
|
||||
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@
|
||||
Open source philosophy is characterized by software development directed by peer production
|
||||
and collaboration through an active community of developers.
|
||||
Contrast this to the more standard centralized development models used by commercial software
|
||||
companies where a finite set of developers produces a product for sale using a defined set
|
||||
companies where a finite set of developers produce a product for sale using a defined set
|
||||
of procedures that ultimately result in an end product whose architecture and source material
|
||||
are closed to the public.
|
||||
</para>
|
||||
@@ -55,7 +55,7 @@
|
||||
</section>
|
||||
|
||||
<section id="usingpoky-changes-collaborate">
|
||||
<title>Using the Yocto Project in a Team Environment</title>
|
||||
<title>Using The Yocto Project in a Team Environment</title>
|
||||
|
||||
<para>
|
||||
It might not be immediately clear how you can use the Yocto Project in a team environment,
|
||||
@@ -97,20 +97,19 @@
|
||||
<para>
|
||||
Most teams have many pieces of software undergoing active development at any given time.
|
||||
You can derive large benefits by putting these pieces under the control of a source
|
||||
control system that is compatible (i.e. Git or Subversion (SVN)) with the OpenEmbeded
|
||||
build system that the Yocto Project uses.
|
||||
control system that is compatible with the Yocto Project (i.e. Git or Subversion (SVN).
|
||||
You can then set the autobuilder to pull the latest revisions of the packages
|
||||
and test the latest commits by the builds.
|
||||
This practice quickly highlights issues.
|
||||
The build system easily supports testing configurations that use both a
|
||||
The Yocto Project easily supports testing configurations that use both a
|
||||
stable known good revision and a floating revision.
|
||||
The build system can also take just the changes from specific source control branches.
|
||||
The Yocto Project can also take just the changes from specific source control branches.
|
||||
This capability allows you to track and test specific changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Perhaps the hardest part of setting this up is defining the software project or
|
||||
the metadata policies that surround the different source control systems.
|
||||
the Yocto Project metadata policies that surround the different source control systems.
|
||||
Of course circumstances will be different in each case.
|
||||
However, this situation reveals one of the Yocto Project's advantages -
|
||||
the system itself does not
|
||||
@@ -130,7 +129,7 @@
|
||||
From the interface, you can click on any particular item in the "Name" column and
|
||||
see the URL at the bottom of the page that you need to set up a Git repository for
|
||||
that particular item.
|
||||
Having a local Git repository of the source directory (poky) allows you to
|
||||
Having a local Git repository of the Yocto Project files allows you to
|
||||
make changes, contribute to the history, and ultimately enhance the Yocto Project's
|
||||
tools, Board Support Packages, and so forth.
|
||||
</para>
|
||||
@@ -148,8 +147,8 @@
|
||||
<ulink url='&YOCTO_HOME_URL;/download'>download page</ulink> and get a
|
||||
tarball of the release.
|
||||
You can also go to this site to download any supported BSP tarballs.
|
||||
Unpacking the tarball gives you a hierarchical source directory that lets you develop
|
||||
using the Yocto Project.
|
||||
Unpacking the tarball gives you a hierarchical directory structure of Yocto Project
|
||||
files that lets you develop using the Yocto Project.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -158,22 +157,22 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In summary, here is where you can get the project files needed for development:
|
||||
In summary, here is where you can get the Yocto Project files needed for development:
|
||||
<itemizedlist>
|
||||
<listitem><para id='source-repositories'><emphasis><ulink url='&YOCTO_GIT_URL;/cgit/cgit.cgi'>Source Repositories:</ulink></emphasis>
|
||||
This area contains IDE Plugins, Matchbox, Poky, Poky Support, Tools, Yocto Linux Kernel, and Yocto
|
||||
Metadata Layers.
|
||||
You can create local copies of Git repositories for each of these areas.</para>
|
||||
You can create Git repositories for each of these areas.</para>
|
||||
<para>
|
||||
<imagedata fileref="figures/source-repos.png" align="center" width="6in" depth="4in" />
|
||||
</para></listitem>
|
||||
<listitem><para><anchor id='index-downloads' /><emphasis><ulink url='&YOCTO_DL_URL;/releases/'>Index of /releases:</ulink></emphasis>
|
||||
This area contains index releases such as
|
||||
the <trademark class='trade'>Eclipse</trademark>
|
||||
Yocto Plug-in, miscellaneous support, poky, pseudo, cross-development toolchains,
|
||||
Yocto Plug-in, miscellaneous support, Poky, pseudo, cross-development toolchains,
|
||||
and all released versions of Yocto Project in the form of images or tarballs.
|
||||
Downloading and extracting these files does not produce a local copy of the
|
||||
Git repository but rather a snapshot of a particular release or image.</para>
|
||||
Downloading and extracting these files does not produce a Git repository but rather
|
||||
a snapshot of a particular release or image.</para>
|
||||
<para>
|
||||
<imagedata fileref="figures/index-downloads.png" align="center" width="6in" depth="4in" />
|
||||
</para></listitem>
|
||||
@@ -200,7 +199,7 @@
|
||||
<listitem><para><emphasis>Append Files:</emphasis> Files that append build information to
|
||||
a recipe file.
|
||||
Append files are known as BitBake append files and <filename>.bbappend</filename> files.
|
||||
The OpenEmbedded build system expects every append file to have a corresponding and
|
||||
The Yocto Project build system expects every append file to have a corresponding and
|
||||
underlying recipe (<filename>.bb</filename>) file.
|
||||
Furthermore, the append file and the underlying recipe must have the same root filename.
|
||||
The filenames can differ only in the file type suffix used (e.g.
|
||||
@@ -212,25 +211,141 @@
|
||||
"<link linkend='changing-recipes-kernel'>Changing <filename>recipes-kernel</filename></link>"
|
||||
sections.</para></listitem>
|
||||
<listitem><para><emphasis>BitBake:</emphasis> The task executor and scheduler used by
|
||||
the OpenEmbedded build system to build images.
|
||||
For more information on BitBake, see the <ulink url='&BITBAKE_DOCS_URL;'>
|
||||
the Yocto Project to build images.
|
||||
For more information on BitBake, see the <ulink url='http://bitbake.berlios.de/manual/'>
|
||||
BitBake documentation</ulink>.</para></listitem>
|
||||
<listitem><para><emphasis>Classes:</emphasis> Files that provide for logic encapsulation
|
||||
and inheritance allowing commonly used patterns to be defined once and easily used
|
||||
in multiple recipes.
|
||||
Class files end with the <filename>.bbclass</filename> filename extension.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Configuration File:</emphasis> Configuration information in various
|
||||
<filename>.conf</filename> files provides global definitions of variables.
|
||||
The <filename>conf/local.conf</filename> configuration file in the
|
||||
<link linkend='yocto-project-build-directory'>Yocto Project Build Directory</link>
|
||||
contains user-defined variables that affect each build.
|
||||
The <filename>meta-yocto/conf/distro/poky.conf</filename> configuration file
|
||||
defines Yocto ‘distro’ configuration
|
||||
variables used only when building with this policy.
|
||||
Machine configuration files, which
|
||||
are located throughout the Yocto Project file structure, define
|
||||
variables for specific hardware and are only used when building for that target
|
||||
(e.g. the <filename>machine/beagleboard.conf</filename> configuration file defines
|
||||
variables for the Texas Instruments ARM Cortex-A8 development board).
|
||||
Configuration files end with a <filename>.conf</filename> filename extension.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Cross-Development Toolchain:</emphasis>
|
||||
A collection of software development
|
||||
tools and utilities that allow you to develop software for targeted architectures.
|
||||
This toolchain contains cross-compilers, linkers, and debuggers that are specific to
|
||||
an architecture.
|
||||
You can use the Yocto Project to build cross-development toolchains in tarball form that when
|
||||
unpacked contain the development tools you need to cross-compile and test your software.
|
||||
The Yocto Project ships with images that contain toolchains for supported architectures
|
||||
as well.
|
||||
Sometimes this toolchain is referred to as the meta-toolchain.</para></listitem>
|
||||
<listitem><para><emphasis>Image:</emphasis> An image is the result produced when
|
||||
BitBake processes a given collection of recipes and related metadata.
|
||||
Images are the binary output that runs on specific hardware and for specific
|
||||
use cases.
|
||||
For a list of the supported image types that the Yocto Project provides, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Reference: Images</ulink>"
|
||||
appendix in The Yocto Project Reference Manual.</para></listitem>
|
||||
<listitem><para id='layer'><emphasis>Layer:</emphasis> A collection of recipes representing the core,
|
||||
a BSP, or an application stack.
|
||||
For a discussion on BSP Layers, see the
|
||||
"<ulink url='&YOCTO_DOCS_BSP_URL;#bsp-layers'>BSP Layers</ulink>"
|
||||
section in the Yocto Project Board Support Packages (BSP) Developer's Guide.</para></listitem>
|
||||
<listitem><para id='metadata'><emphasis>Metadata:</emphasis> The files that BitBake parses when
|
||||
building an image.
|
||||
Metadata includes recipes, classes, and configuration files.</para></listitem>
|
||||
<listitem><para><emphasis>OE-Core:</emphasis> A core set of metadata originating
|
||||
with OpenEmbedded (OE) that is shared between OE and the Yocto Project.
|
||||
This metadata is found in the <filename>meta</filename> directory of the Yocto Project
|
||||
files.</para></listitem>
|
||||
<listitem><para><emphasis>Package:</emphasis> The packaged output from a baked recipe.
|
||||
A package is generally the compiled binaries produced from the recipe's sources.
|
||||
You ‘bake’ something by running it through BitBake.</para></listitem>
|
||||
<listitem><para><emphasis>Poky:</emphasis> The build tool that the Yocto Project
|
||||
uses to create images.</para></listitem>
|
||||
<listitem><para><emphasis>Recipe:</emphasis> A set of instructions for building packages.
|
||||
A recipe describes where you get source code and which patches to apply.
|
||||
Recipes describe dependencies for libraries or for other recipes, and they
|
||||
also contain configuration and compilation options.
|
||||
Recipes contain the logical unit of execution, the software/images to build, and
|
||||
use the <filename>.bb</filename> file extension.</para></listitem>
|
||||
<listitem><para><emphasis>Tasks:</emphasis> Arbitrary groups of software Recipes.
|
||||
You simply use Tasks to hold recipes that, when built, usually accomplish a single task.
|
||||
For example, a task could contain the recipes for a company’s proprietary or value-add software.
|
||||
Or, the task could contain the recipes that enable graphics.
|
||||
A task is really just another recipe.
|
||||
Because task files are recipes, they end with the <filename>.bb</filename> filename
|
||||
extension.</para></listitem>
|
||||
<listitem><para><emphasis>Upstream:</emphasis> A reference to source code or repositories
|
||||
that are not local to the development system but located in a master area that is controlled
|
||||
by the maintainer of the source code.
|
||||
For example, in order for a developer to work on a particular piece of code, they need to
|
||||
first get a copy of it from an "upstream" source.</para></listitem>
|
||||
<listitem>
|
||||
<para id='build-directory'><emphasis>Build Directory:</emphasis>
|
||||
This term refers to the area used by the OpenEmbedded build system for builds.
|
||||
The area is created when you <filename>source</filename> the setup
|
||||
environment script that is found in the source directory
|
||||
<para id='yocto-project-files'><emphasis>Yocto Project Files:</emphasis>
|
||||
This term refers to the directory structure created as a result of either downloading
|
||||
and unpacking a Yocto Project release tarball or setting up a Git repository
|
||||
by cloning <filename>git://git.yoctoproject.org/poky</filename>.
|
||||
Sometimes the term "the Yocto Project Files structure" is used as well.</para>
|
||||
|
||||
<para>The Yocto Project Files contain BitBake, Documentation, metadata and
|
||||
other files that all support the development environment.
|
||||
Consequently, you must have the Yocto Project Files in place on your development
|
||||
system in order to do any development using the Yocto Project.</para>
|
||||
|
||||
<para>The name of the top-level directory of the Yocto Project Files structure
|
||||
is derived from the Yocto Project release tarball.
|
||||
For example, downloading and unpacking <filename>&YOCTO_POKY_TARBALL;</filename>
|
||||
results in a Yocto Project file structure whose Yocto Project source directory is named
|
||||
<filename>&YOCTO_POKY;</filename>.
|
||||
If you create a Git repository, then you can name the repository anything you like.
|
||||
Throughout much of the documentation, the name of the Git repository is used as the
|
||||
name for the local folder.
|
||||
So, for example, cloning the <filename>poky</filename> Git repository results in a
|
||||
local Git repository also named <filename>poky</filename>.</para>
|
||||
|
||||
<para>It is important to understand the differences between Yocto Project Files created
|
||||
by unpacking a release tarball as compared to cloning
|
||||
<filename>git://git.yoctoproject.org/poky</filename>.
|
||||
When you unpack a tarball, you have an exact copy of the files based on the time of
|
||||
release - a fixed release point.
|
||||
Any changes you make to your local Yocto Project Files are on top of the release.
|
||||
On the other hand, when you clone the Yocto Project Git repository, you have an
|
||||
active development repository.
|
||||
In this case, any local changes you make to the Yocto Project can be later applied
|
||||
to active development branches of the upstream Yocto Project Git repository.</para>
|
||||
|
||||
<para>Finally, if you want to track a set of local changes while starting from the same point
|
||||
as a release tarball, you can create a local Git branch that
|
||||
reflects the exact copy of the files at the time of their release.
|
||||
You do this using Git tags that are part of the repository.</para>
|
||||
|
||||
<para>For more information on concepts around Git repositories, branches, and tags,
|
||||
see the
|
||||
"<link linkend='repositories-tags-and-branches'>Repositories, Tags, and Branches</link>"
|
||||
section.</para></listitem>
|
||||
<listitem>
|
||||
<para id='yocto-project-build-directory'><emphasis>Yocto Project Build Directory:</emphasis>
|
||||
This term refers to the area used by the Yocto Project for builds.
|
||||
The area is created when you <filename>source</filename> the Yocto Project setup
|
||||
environment script that is found in the Yocto Project files area
|
||||
(i.e. <filename>oe-init-build-env</filename>).
|
||||
The <ulink url='&YOCTO_DOCS_REF_URL;#var-TOPDIR'><filename>TOPDIR</filename></ulink>
|
||||
variable points to the build directory.</para>
|
||||
|
||||
<para>You have a lot of flexibility when creating the build directory.
|
||||
<para>You have a lot of flexibility when creating the Yocto Project Build Directory.
|
||||
Following are some examples that show how to create the directory:
|
||||
<itemizedlist>
|
||||
<listitem><para>Create the build directory in your current working directory
|
||||
and name it <filename>build</filename>.
|
||||
This is the default behavior.
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source oe-init-build-env
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Provide a directory path and specifically name the build
|
||||
@@ -249,140 +364,6 @@
|
||||
</literallayout></para></listitem>
|
||||
</itemizedlist>
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Build System:</emphasis> In the context of the Yocto Project
|
||||
this term refers to the OpenEmbedded build system used by the project.
|
||||
This build system is based on the project known as "Poky."
|
||||
For some historical information about Poky, see the
|
||||
<link linkend='poky'>poky</link> term further along in this section.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Classes:</emphasis> Files that provide for logic encapsulation
|
||||
and inheritance allowing commonly used patterns to be defined once and easily used
|
||||
in multiple recipes.
|
||||
Class files end with the <filename>.bbclass</filename> filename extension.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Configuration File:</emphasis> Configuration information in various
|
||||
<filename>.conf</filename> files provides global definitions of variables.
|
||||
The <filename>conf/local.conf</filename> configuration file in the
|
||||
<link linkend='build-directory'>build directory</link>
|
||||
contains user-defined variables that affect each build.
|
||||
The <filename>meta-yocto/conf/distro/poky.conf</filename> configuration file
|
||||
defines Yocto ‘distro’ configuration
|
||||
variables used only when building with this policy.
|
||||
Machine configuration files, which
|
||||
are located throughout the
|
||||
<link linkend='source-directory'>source directory</link>, define
|
||||
variables for specific hardware and are only used when building for that target
|
||||
(e.g. the <filename>machine/beagleboard.conf</filename> configuration file defines
|
||||
variables for the Texas Instruments ARM Cortex-A8 development board).
|
||||
Configuration files end with a <filename>.conf</filename> filename extension.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Cross-Development Toolchain:</emphasis>
|
||||
A collection of software development
|
||||
tools and utilities that allow you to develop software for targeted architectures.
|
||||
This toolchain contains cross-compilers, linkers, and debuggers that are specific to
|
||||
an architecture.
|
||||
You can use the OpenEmbedded build system to build cross-development toolchains in tarball
|
||||
form that, when
|
||||
unpacked, contain the development tools you need to cross-compile and test your software.
|
||||
The Yocto Project ships with images that contain toolchains for supported architectures
|
||||
as well.
|
||||
Sometimes this toolchain is referred to as the meta-toolchain.</para></listitem>
|
||||
<listitem><para><emphasis>Image:</emphasis> An image is the result produced when
|
||||
BitBake processes a given collection of recipes and related metadata.
|
||||
Images are the binary output that run on specific hardware and for specific
|
||||
use cases.
|
||||
For a list of the supported image types that the Yocto Project provides, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Images</ulink>"
|
||||
chapter in the Yocto Project Reference Manual.</para></listitem>
|
||||
<listitem><para id='layer'><emphasis>Layer:</emphasis> A collection of recipes representing the core,
|
||||
a BSP, or an application stack.
|
||||
For a discussion on BSP Layers, see the
|
||||
"<ulink url='&YOCTO_DOCS_BSP_URL;#bsp-layers'>BSP Layers</ulink>"
|
||||
section in the Yocto Project Board Support Packages (BSP) Developer's Guide.</para></listitem>
|
||||
<listitem><para id='metadata'><emphasis>Metadata:</emphasis> The files that BitBake parses when
|
||||
building an image.
|
||||
Metadata includes recipes, classes, and configuration files.</para></listitem>
|
||||
<listitem><para><emphasis>OE-Core:</emphasis> A core set of metadata originating
|
||||
with OpenEmbedded (OE) that is shared between OE and the Yocto Project.
|
||||
This metadata is found in the <filename>meta</filename> directory of the source
|
||||
directory.</para></listitem>
|
||||
<listitem><para><emphasis>Package:</emphasis> The packaged output from a baked recipe.
|
||||
A package is generally the compiled binaries produced from the recipe's sources.
|
||||
You ‘bake’ something by running it through BitBake.</para></listitem>
|
||||
<listitem><para id='poky'><emphasis>Poky:</emphasis> The term "poky" can mean several things.
|
||||
In its most general sence, it is an open-source project that was initially developed
|
||||
by OpenedHand. With OpenedHand, poky was developed off of the existing OpenEmbedded
|
||||
build system becoming a build system for embedded images.
|
||||
After Intel Corporation aquired OpenedHand, the project poky became the basis for
|
||||
the Yocto Project's build system.
|
||||
Within the Yocto Project source repositories, poky exists as a separate Git repository
|
||||
that can be cloned to yield a local copy on the host system.
|
||||
Thus, "poky" can refer to the local copy of the source directory used to develop within
|
||||
the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>Recipe:</emphasis> A set of instructions for building packages.
|
||||
A recipe describes where you get source code and which patches to apply.
|
||||
Recipes describe dependencies for libraries or for other recipes, and they
|
||||
also contain configuration and compilation options.
|
||||
Recipes contain the logical unit of execution, the software/images to build, and
|
||||
use the <filename>.bb</filename> file extension.</para></listitem>
|
||||
<listitem>
|
||||
<para id='source-directory'><emphasis>Source Directory:</emphasis>
|
||||
This term refers to the directory structure created as a result of either downloading
|
||||
and unpacking a Yocto Project release tarball or creating a local copy of
|
||||
<filename>poky</filename> Git repository <filename>git://git.yoctoproject.org/poky</filename>.
|
||||
Sometimes you might here the term "poky directory" used to refer to this
|
||||
directory structure.</para>
|
||||
|
||||
<para>The source directory contains BitBake, Documentation, metadata and
|
||||
other files that all support the Yocto Project.
|
||||
Consequently, you must have the source directory in place on your development
|
||||
system in order to do any development using the Yocto Project.</para>
|
||||
|
||||
<para>For tarball expansion, the name of the top-level directory of the source directory
|
||||
is derived from the Yocto Project release tarball.
|
||||
For example, downloading and unpacking <filename>&YOCTO_POKY_TARBALL;</filename>
|
||||
results in a source directory whose top-level folder is named
|
||||
<filename>&YOCTO_POKY;</filename>.
|
||||
If you create a local copy of the Git repository, then you can name the repository
|
||||
anything you like.
|
||||
Throughout much of the documentation, <filename>poky</filename> is used as the name of
|
||||
the top-level folder of the local copy of the poky Git repository.
|
||||
So, for example, cloning the <filename>poky</filename> Git repository results in a
|
||||
local Git repository whose top-level folder is also named <filename>poky</filename>.</para>
|
||||
|
||||
<para>It is important to understand the differences between the source directory created
|
||||
by unpacking a released tarball as compared to cloning
|
||||
<filename>git://git.yoctoproject.org/poky</filename>.
|
||||
When you unpack a tarball, you have an exact copy of the files based on the time of
|
||||
release - a fixed release point.
|
||||
Any changes you make to your local files in the source directory are on top of the release.
|
||||
On the other hand, when you clone the <filename>poky</filename> Git repository, you have an
|
||||
active development repository.
|
||||
In this case, any local changes you make to the source directory can be later applied
|
||||
to active development branches of the upstream <filename>poky</filename> Git
|
||||
repository.</para>
|
||||
|
||||
<para>Finally, if you want to track a set of local changes while starting from the same point
|
||||
as a release tarball, you can create a local Git branch that
|
||||
reflects the exact copy of the files at the time of their release.
|
||||
You do this using Git tags that are part of the repository.</para>
|
||||
|
||||
<para>For more information on concepts around Git repositories, branches, and tags,
|
||||
see the
|
||||
"<link linkend='repositories-tags-and-branches'>Repositories, Tags, and Branches</link>"
|
||||
section.</para></listitem>
|
||||
<listitem><para><emphasis>Tasks:</emphasis> Arbitrary groups of software Recipes.
|
||||
You simply use Tasks to hold recipes that, when built, usually accomplish a single task.
|
||||
For example, a task could contain the recipes for a company’s proprietary or value-add software.
|
||||
Or, the task could contain the recipes that enable graphics.
|
||||
A task is really just another recipe.
|
||||
Because task files are recipes, they end with the <filename>.bb</filename> filename
|
||||
extension.</para></listitem>
|
||||
<listitem><para><emphasis>Upstream:</emphasis> A reference to source code or repositories
|
||||
that are not local to the development system but located in a master area that is controlled
|
||||
by the maintainer of the source code.
|
||||
For example, in order for a developer to work on a particular piece of code, they need to
|
||||
first get a copy of it from an "upstream" source.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
@@ -422,7 +403,7 @@
|
||||
<filename>meta/files/common-licenses</filename>.
|
||||
Once the build completes, the list of all licenses found and used during that build are
|
||||
kept in the
|
||||
<link linkend='build-directory'>build directory</link> at
|
||||
<link linkend='yocto-project-build-directory'>Yocto Project Build Directory</link> at
|
||||
<filename>tmp/deploy/images/licenses</filename>.
|
||||
</para>
|
||||
|
||||
@@ -549,9 +530,9 @@
|
||||
$ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME;
|
||||
</literallayout>
|
||||
In this example, the name of the top-level directory of your local Yocto Project
|
||||
Files Git repository is <filename>poky</filename>,
|
||||
and the name of the local working area (or local branch) you have created and checked
|
||||
out is <filename>&DISTRO_NAME;</filename>.
|
||||
Files Git repository is <filename>poky</filename>.
|
||||
And, the name of the local working area (or local branch) you have created and checked
|
||||
out is named <filename>&DISTRO_NAME;</filename>.
|
||||
The files in your repository now reflect the same files that are in the
|
||||
<filename>&DISTRO_NAME;</filename> development branch of the Yocto Project's
|
||||
<filename>poky</filename> repository.
|
||||
@@ -874,53 +855,54 @@
|
||||
<listitem><para>Submit the bug by clicking the "Submit Bug" button.</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<note>
|
||||
Bugs in the Yocto Project Bugzilla follow naming convention:
|
||||
<filename>[YOCTO #<number>]</filename>, where <filename><number></filename> is the
|
||||
assigned defect ID used in Bugzilla.
|
||||
So, for example, a valid way to refer to a defect would be <filename>[YOCTO #1011]</filename>.
|
||||
This convention becomes important if you are submitting patches against the Yocto Project
|
||||
code itself.
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id='how-to-submit-a-change'>
|
||||
<title>How to Submit a Change</title>
|
||||
|
||||
<para>
|
||||
Contributions to the Yocto Project and OpenEmbedded are very welcome.
|
||||
Because the system is extremely configurable and flexible, we recognize that developers
|
||||
Contributions to the Yocto Project are very welcome.
|
||||
Because the Yocto Project is extremely configurable and flexible, we recognize that developers
|
||||
will want to extend, configure or optimize it for their specific uses.
|
||||
You should send patches to the appropriate mailing list so that they
|
||||
can be reviewed and merged by the appropriate maintainer.
|
||||
For a list of the Yocto Project and related mailing lists, see the
|
||||
You should send patches to the appropriate Yocto Project mailing list to get them
|
||||
in front of the Yocto Project Maintainer.
|
||||
For a list of the Yocto Project mailing lists, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#resources-mailinglist'>Mailing lists</ulink>" section in
|
||||
The Yocto Project Reference Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following is some guidance on which mailing list to use for what type of change:
|
||||
The following is some guidance on which mailing list to use for what type of defect:
|
||||
<itemizedlist>
|
||||
<listitem><para>For changes to the core metadata, send your patch to the
|
||||
<ulink url='&OE_LISTS_URL;/listinfo/openembedded-core'>openembedded-core</ulink> mailing list.
|
||||
For example, a change to anything under the <filename>meta</filename> or
|
||||
<filename>scripts</filename> directories
|
||||
should be sent to this mailing list.</para></listitem>
|
||||
<listitem><para>For changes to BitBake (anything under the <filename>bitbake</filename>
|
||||
directory), send your patch to the
|
||||
<ulink url='&OE_LISTS_URL;/listinfo/bitbake-devel'>bitbake-devel</ulink> mailing list.</para></listitem>
|
||||
<listitem><para>For changes to <filename>meta-yocto</filename>, send your patch to the
|
||||
<ulink url='&YOCTO_LISTS_URL;/listinfo/poky'>poky</ulink> mailing list.</para></listitem>
|
||||
<listitem><para>For changes to other layers hosted on yoctoproject.org (unless the
|
||||
layer's documentation specifies otherwise), tools, and Yocto Project
|
||||
documentation, use the
|
||||
<ulink url='&YOCTO_LISTS_URL;/listinfo/yocto'>yocto</ulink> mailing list.</para></listitem>
|
||||
<listitem><para>For additional recipes that do not fit into the core metadata,
|
||||
you should determine which layer the recipe should go into and submit the
|
||||
change in the manner recommended by the documentation (e.g. README) supplied
|
||||
with the layer. If in doubt, please ask on the
|
||||
<ulink url='&YOCTO_LISTS_URL;/listinfo/yocto'>yocto</ulink> or
|
||||
<ulink url='&OE_LISTS_URL;/listinfo/openembedded-devel'>openembedded-devel</ulink>
|
||||
mailing lists.</para></listitem>
|
||||
<listitem><para>For defects against the Yocto Project build system Poky, send
|
||||
your patch to the
|
||||
<ulink url='&YOCTO_LISTS_URL;/listinfo/poky'></ulink> mailing list.
|
||||
This mailing list corresponds to issues that are not specific to the Yocto Project but
|
||||
are part of the OE-core.
|
||||
For example, a defect against anything in the <filename>meta</filename> layer
|
||||
or the BitBake Manual could be sent to this mailing list.</para></listitem>
|
||||
<listitem><para>For defects against Yocto-specific layers, tools, and Yocto Project
|
||||
documentation use the
|
||||
<ulink url='&YOCTO_LISTS_URL;/listinfo/yocto'></ulink> mailing list.
|
||||
This mailing list corresponds to Yocto-specific areas such as
|
||||
<filename>meta-yocto</filename>, <filename>meta-intel</filename>,
|
||||
<filename>linux-yocto</filename>, and <filename>documentation</filename>.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you send a patch, be sure to include a "Signed-off-by:"
|
||||
line in the same style as required by the Linux kernel.
|
||||
Adding this line signifies that you, the submitter, have agreed to the Developer's Certificate of Origin 1.1
|
||||
Adding this line signifies the developer has agreed to the Developer's Certificate of Origin 1.1
|
||||
as follows:
|
||||
<literallayout class='monospaced'>
|
||||
Developer's Certificate of Origin 1.1
|
||||
@@ -949,52 +931,52 @@
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
</literallayout>
|
||||
A Poky contributions tree (<filename>poky-contrib</filename>,
|
||||
<filename>git://git.yoctoproject.org/poky-contrib.git</filename>)
|
||||
exists for contributors to stage contributions.
|
||||
If people desire such access, please ask on the mailing list.
|
||||
Usually, the Yocto Project team will grant access to anyone with a proven track
|
||||
record of good patches.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In a collaborative environment, it is necessary to have some sort of standard
|
||||
or method through which you submit changes.
|
||||
Otherwise, things could get quite chaotic.
|
||||
One general practice to follow is to make small, controlled changes.
|
||||
Keeping changes small and isolated aids review, makes merging/rebasing easier
|
||||
and keeps the change history clean when anyone needs to refer to it in future.
|
||||
One general practice to follow is to make small, controlled changes to the
|
||||
Yocto Project.
|
||||
Keeping changes small and isolated lets you best keep pace with future Yocto Project changes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you make a commit, you must follow certain standards established by the
|
||||
OpenEmbedded and Yocto Project development teams.
|
||||
For each commit, you must provide a single-line summary of the change and you
|
||||
should almost always provide a more detailed description of what you did (i.e.
|
||||
the body of the commit message).
|
||||
When you create a commit, you must follow certain standards established by the
|
||||
Yocto Project development team.
|
||||
For each commit, you must provide a single-line summary of the change and you
|
||||
almost always provide a more detailed description of what you did (i.e. the body
|
||||
of the commit).
|
||||
The only exceptions for not providing a detailed description would be if your
|
||||
change is a simple, self-explanatory change that needs no description.
|
||||
Here are the guidelines for composing a commit message:
|
||||
Here are the Yocto Project commit message guidelines:
|
||||
<itemizedlist>
|
||||
<listitem><para>Provide a single-line, short summary of the change.
|
||||
This summary is typically viewable in the "shortlist" of changes.
|
||||
This summary is typically viewable by source control systems.
|
||||
Thus, providing something short and descriptive that gives the reader
|
||||
a summary of the change is useful when viewing a list of many commits.
|
||||
This should be prefixed by the recipe name (if changing a recipe), or
|
||||
else the short form path to the file being changed.
|
||||
</para></listitem>
|
||||
<listitem><para>For the body of the commit message, provide detailed information
|
||||
that describes what you changed, why you made the change, and the approach
|
||||
you used. It may also be helpful if you mention how you tested the change.
|
||||
you used.
|
||||
Provide as much detail as you can in the body of the commit message.
|
||||
</para></listitem>
|
||||
<listitem><para>If the change addresses a specific bug or issue that is
|
||||
associated with a bug-tracking ID, include a reference to that ID in
|
||||
your detailed description.
|
||||
For example, the Yocto Project uses a specific convention for bug
|
||||
references - any commit that addresses a specific bug should include the
|
||||
bug ID in the description (typically at the end) as follows:
|
||||
associated with a bug-tracking ID, prefix your detailed description
|
||||
with the bug or issue ID.
|
||||
For example, the Yocto Project tracks bugs using a bug-naming convention.
|
||||
Any commits that address a bug must start with the bug ID in the description
|
||||
as follows:
|
||||
<literallayout class='monospaced'>
|
||||
<detailed description of change>
|
||||
|
||||
[YOCTO #<bug-id>]
|
||||
YOCTO #<bug-id>: <Detailed description of commit>
|
||||
</literallayout></para></listitem>
|
||||
Where <bug-id> is replaced with the specific bug ID from the
|
||||
Yocto Project Bugzilla instance.
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@@ -1015,11 +997,11 @@
|
||||
The basic flow for pushing a change to an upstream "contrib" Git repository is as follows:
|
||||
<itemizedlist>
|
||||
<listitem><para>Make your changes in your local Git repository.</para></listitem>
|
||||
<listitem><para>Stage your changes by using the <filename>git add</filename>
|
||||
command on each file you changed.</para></listitem>
|
||||
<listitem><para>Stage your commit (or change) by using the <filename>git add</filename>
|
||||
command.</para></listitem>
|
||||
<listitem><para>Commit the change by using the <filename>git commit</filename>
|
||||
command and push it to the "contrib" repository.
|
||||
Be sure to provide a commit message that follows the project’s commit message standards
|
||||
Be sure to provide a commit message that follows the project’s commit standards
|
||||
as described earlier.</para></listitem>
|
||||
<listitem><para>Notify the maintainer that you have pushed a change by making a pull
|
||||
request.
|
||||
@@ -1030,10 +1012,10 @@
|
||||
You can find these scripts in the <filename>scripts</filename> directory of the
|
||||
Yocto Project file structure.</para>
|
||||
<para>For help on using these scripts, simply provide the
|
||||
<filename>-h</filename> argument as follows:
|
||||
<filename>--help</filename> argument as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ ~/poky/scripts/create-pull-request -h
|
||||
$ ~/poky/scripts/send-pull-request -h
|
||||
$ ~/poky/scripts/create-pull-request --help
|
||||
$ ~/poky/scripts/send-pull-request --help
|
||||
</literallayout></para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
@@ -1048,24 +1030,13 @@
|
||||
<title>Submitting a Patch Through Email</title>
|
||||
|
||||
<para>
|
||||
If you have a just few changes, you can commit them and then submit them as an
|
||||
If you have a just a few changes, you can commit them and then submit them as an
|
||||
email to the maintainer.
|
||||
Depending on the components changed, you need to submit the email to a specific
|
||||
mailing list.
|
||||
For some guidance on which mailing list to use, see the list in the
|
||||
"<link linkend='how-to-submit-a-change'>How to Submit a Change</link>" section
|
||||
earlier in this manual.
|
||||
For a description of the available mailing lists, see
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#resources-mailinglist'>Mailing Lists</ulink>"
|
||||
section in the Yocto Project Reference Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is the general procedure on how to submit a patch through email:
|
||||
Here is a general procedure:
|
||||
<itemizedlist>
|
||||
<listitem><para>Make your changes in your local Git repository.</para></listitem>
|
||||
<listitem><para>Stage your changes by using the <filename>git add</filename>
|
||||
command on each file you changed.</para></listitem>
|
||||
<listitem><para>Stage your commit (or change) by using the <filename>git add</filename>
|
||||
command.</para></listitem>
|
||||
<listitem><para>Commit the change by using the
|
||||
<filename>git commit --signoff</filename> command.
|
||||
Using the <filename>--signoff</filename> option identifies you as the person
|
||||
@@ -1098,17 +1069,7 @@
|
||||
the series of patches.
|
||||
For information on the <filename>git format-patch</filename> command,
|
||||
see <filename>GIT_FORMAT_PATCH(1)</filename> displayed using the
|
||||
<filename>man git-format-patch</filename> command.</para>
|
||||
<note>If you have many patches to submit, you might consider using the
|
||||
method described in the "<link linkend='pushing-a-change-upstream'>Pushing
|
||||
a change Upstream and Requesting a Pull</link>" section described
|
||||
earlier in the manual.
|
||||
This method uses the <filename>create-pull-request</filename> and
|
||||
<filename>send-pull-request</filename> scripts that automate much of the
|
||||
process.
|
||||
You might also consider requesting a contrib area and the associated rights
|
||||
needed if you become a regular contributor to either the Yocto Project or
|
||||
OpenEmbedded.</note></listitem>
|
||||
<filename>man git-format-patch</filename> command.</para></listitem>
|
||||
<listitem><para>Import the files into your mail client by using the
|
||||
<filename>git send-email</filename> command.
|
||||
<note>In order to use <filename>git send-email</filename>, you must have the
|
||||
|
||||
@@ -24,16 +24,15 @@
|
||||
|
||||
<para>
|
||||
The Yocto Project is an open-source collaboration project focused on embedded Linux development.
|
||||
The project currently provides a build system, which is
|
||||
referred to as the OpenEmbedded build system in the Yocto Project documentation.
|
||||
The Yocto Project provides various ancillary tools suitable for the embedded developer
|
||||
and also features the Sato reference User Interface, which is optimized for
|
||||
The project currently provides a build system, which is sometimes referred to as "Poky",
|
||||
and provides various ancillary tools suitable for the embedded developer.
|
||||
The Yocto Project also features the Sato reference User Interface, which is optimized for
|
||||
stylus driven, low-resolution screens.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can use the OpenEmbedded build system, which uses
|
||||
<ulink url='&BITBAKE_DOCS_URL;'>BitBake</ulink>, to develop complete Linux
|
||||
You can use the Yocto Project build system, which uses
|
||||
<ulink url='http://bitbake.berlios.de/manual/'>BitBake</ulink>, to develop complete Linux
|
||||
images and associated user-space applications for architectures based on ARM, MIPS, PowerPC,
|
||||
x86 and x86-64.
|
||||
While the Yocto Project does not provide a strict testing framework,
|
||||
@@ -54,50 +53,56 @@
|
||||
<listitem><para><emphasis>Host System:</emphasis> You should have a reasonably current
|
||||
Linux-based host system.
|
||||
You will have the best results with a recent release of Fedora,
|
||||
OpenSUSE, Ubuntu, or CentOS as these releases are frequently tested against the Yocto Project
|
||||
OpenSUSE, or Ubuntu as these releases are frequently tested against the Yocto Project
|
||||
and officially supported.
|
||||
You should also have about 100 gigabytes of free disk space for building images.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Packages:</emphasis> The OpenEmbedded build system
|
||||
requires certain packages exist on your development system (e.g. Python 2.6 or 2.7).
|
||||
<listitem><para><emphasis>Packages:</emphasis> The Yocto Project requires certain packages
|
||||
exist on your development system (e.g. Python 2.6 or 2.7).
|
||||
See "<ulink url='&YOCTO_DOCS_QS_URL;#packages'>The Packages</ulink>"
|
||||
section in the Yocto Project Quick Start for the exact package
|
||||
section in the Yocto Project Quick start for the exact package
|
||||
requirements and the installation commands to install them
|
||||
for the supported distributions.</para></listitem>
|
||||
<listitem id='local-yp-release'><para><emphasis>Yocto Project Release:</emphasis>
|
||||
You need a release of the Yocto Project.
|
||||
You set up a with local <link linkend='source-directory'>source directory</link>
|
||||
one of two ways depending on whether you
|
||||
are going to contribute back into the Yocto Project or not.
|
||||
You can get set up with local
|
||||
<link linkend='yocto-project-files'>Yocto Project Files</link> one of two ways
|
||||
depending on whether you
|
||||
are going to be contributing back into the Yocto Project source repository or not.
|
||||
<note>
|
||||
Regardless of the method you use, this manual refers to the resulting local
|
||||
hierarchical set of files as the "source directory."
|
||||
Regardless of the method you use, this manual refers to the resulting
|
||||
hierarchical set of files as the "Yocto Project Files" or the "Yocto Project File
|
||||
Structure."
|
||||
</note>
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Tarball Extraction:</emphasis> If you are not going to contribute
|
||||
back into the Yocto Project, you can simply download a Yocto Project release you want
|
||||
back into the Yocto Project, you can simply download the Yocto Project release you want
|
||||
from the website’s <ulink url='&YOCTO_HOME_URL;/download'>download page</ulink>.
|
||||
Once you have the tarball, just extract it into a directory of your choice.</para>
|
||||
<para>For example, the following command extracts the Yocto Project &DISTRO;
|
||||
release tarball
|
||||
into the current working directory and sets up the local source directory
|
||||
with a top-level folder named <filename>&YOCTO_POKY;</filename>:
|
||||
into the current working directory and sets up the Yocto Project file structure
|
||||
with a top-level directory named <filename>&YOCTO_POKY;</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ tar xfj &YOCTO_POKY_TARBALL;
|
||||
</literallayout></para>
|
||||
<para>This method does not produce a local Git repository.
|
||||
Instead, you simply end up with a snapshot of the release.</para></listitem>
|
||||
<para>This method does not produce a Git repository.
|
||||
Instead, you simply end up with a local snapshot of the
|
||||
Yocto Project files that are based on the particular release in the
|
||||
tarball.</para></listitem>
|
||||
<listitem><para><emphasis>Git Repository Method:</emphasis> If you are going to be contributing
|
||||
back into the Yocto Project or you simply want to keep up
|
||||
with the latest developments, you should use Git commands to set up a local
|
||||
Git repository of the upstream <filename>poky</filename> source repository.
|
||||
Doing so creates a repository with a complete history of changes and allows
|
||||
Git repository of the Yocto Project Files.
|
||||
Doing so creates a Git repository with a complete history of changes and allows
|
||||
you to easily submit your changes upstream to the project.
|
||||
Because you cloned the repository, you have access to all the Yocto Project development
|
||||
branches and tag names used in the upstream repository.</para>
|
||||
<para>The following transcript shows how to clone the <filename>poky</filename>
|
||||
<para>The following transcript shows how to clone the Yocto Project Files'
|
||||
Git repository into the current working directory.
|
||||
<note>You can view the Yocto Project Source Repositories at
|
||||
<note>The name of the Yocto Project Files Git repository in the Yocto Project Files
|
||||
Source Repositories is <filename>poky</filename>.
|
||||
You can view the Yocto Project Source Repositories at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink></note>
|
||||
The command creates the local repository in a directory named <filename>poky</filename>.
|
||||
For information on Git used within the Yocto Project, see the
|
||||
@@ -116,21 +121,21 @@
|
||||
wiki page</ulink>, which describes how to create both <filename>poky</filename>
|
||||
and <filename>meta-intel</filename> Git repositories.</para></listitem>
|
||||
</itemizedlist></para></listitem>
|
||||
<listitem id='local-kernel-files'><para><emphasis>Yocto Project Kernel:</emphasis>
|
||||
If you are going to be making modifications to a supported Yocto Project kernel, you
|
||||
<listitem id='local-kernel-files'><para><emphasis>Linux Yocto Kernel:</emphasis>
|
||||
If you are going to be making modifications to a supported Linux Yocto kernel, you
|
||||
need to establish local copies of the source.
|
||||
You can find Git repositories of supported Yocto Project Kernels organized under
|
||||
"Yocto Project Linux Kernel" in the Yocto Project Source Repositories at
|
||||
You can find Git repositories of supported Linux Yocto Kernels organized under
|
||||
"Yocto Linux Kernel" in the Yocto Project Source Repositories at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink>.</para>
|
||||
<para>This setup involves creating a bare clone of the Yocto Project kernel and then
|
||||
<para>This setup involves creating a bare clone of the Linux Yocto kernel and then
|
||||
copying that cloned repository.
|
||||
You can create the bare clone and the copy of the bare clone anywhere you like.
|
||||
For simplicity, it is recommended that you create these structures outside of the
|
||||
source directory (usually <filename>poky</filename>).</para>
|
||||
Yocto Project Files Git repository.</para>
|
||||
<para>As an example, the following transcript shows how to create the bare clone
|
||||
of the <filename>linux-yocto-3.2</filename> kernel and then create a copy of
|
||||
that clone.
|
||||
<note>When you have a local Yocto Project kernel Git repository, you can
|
||||
<note>When you have a local Linux Yocto kernel Git repository, you can
|
||||
reference that repository rather than the upstream Git repository as
|
||||
part of the <filename>clone</filename> command.
|
||||
Doing so can speed up the process.</note></para>
|
||||
@@ -161,14 +166,15 @@
|
||||
edit to point to your locally modified kernel source files and to build the kernel
|
||||
image.
|
||||
Pointing to these local files is much more efficient than requiring a download of the
|
||||
kernel's source files from upstream each time you make changes to the kernel.</para>
|
||||
source files from upstream each time you make changes to the kernel.</para>
|
||||
<para>You can find the <filename>poky-extras</filename> Git Repository in the
|
||||
"Yocto Metadata Layers" area of the Yocto Project Source Repositories at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink>.
|
||||
It is good practice to create this Git repository inside the source directory.</para>
|
||||
It is good practice to create this Git repository inside the Yocto Project
|
||||
files Git repository.</para>
|
||||
<para>Following is an example that creates the <filename>poky-extras</filename> Git
|
||||
repository inside the source directory, which is named <filename>poky</filename>
|
||||
in this case:
|
||||
repository inside the Yocto Project files Git repository, which is named
|
||||
<filename>poky</filename> in this case:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/poky-extras poky-extras
|
||||
Initialized empty Git repository in /home/scottrif/poky/poky-extras/.git/
|
||||
@@ -188,7 +194,7 @@
|
||||
layer.
|
||||
You can get set up for BSP development one of two ways: tarball extraction or
|
||||
with a local Git repository.
|
||||
It is a good idea to use the same method that you used to set up the source directory.
|
||||
It is a good idea to use the same method used to set up the Yocto Project Files.
|
||||
Regardless of the method you use, the Yocto Project uses the following BSP layer
|
||||
naming scheme:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -214,16 +220,16 @@
|
||||
Again, this method just produces a snapshot of the BSP layer in the form
|
||||
of a hierarchical directory structure.</para></listitem>
|
||||
<listitem><para><emphasis>Git Repository Method:</emphasis> If you are working
|
||||
with a local Git repository for your source directory, you should also use this method
|
||||
with a Yocto Project Files Git repository, you should also use this method
|
||||
to set up the <filename>meta-intel</filename> Git repository.
|
||||
You can locate the <filename>meta-intel</filename> Git repository in the
|
||||
"Yocto Metadata Layers" area of the Yocto Project Source Repositories at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink>.</para>
|
||||
<para>Typically, you set up the <filename>meta-intel</filename> Git repository inside
|
||||
the source directory.
|
||||
the Yocto Project Files Git repository.
|
||||
For example, the following transcript shows the steps to clone the
|
||||
<filename>meta-intel</filename>
|
||||
Git repository inside the local <filename>poky</filename> Git repository.
|
||||
Git repository inside the <filename>poky</filename> Git repository.
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/meta-intel.git
|
||||
Initialized empty Git repository in /home/scottrif/poky/meta-intel/.git/
|
||||
@@ -242,8 +248,9 @@
|
||||
applications using the Eclipse Integrated Development Environment (IDE),
|
||||
you will need this plug-in.
|
||||
See the
|
||||
"<link linkend='setting-up-the-eclipse-ide'>Setting up the Eclipse IDE</link>"
|
||||
section for more information.</para></listitem>
|
||||
"<ulink url='&YOCTO_DOCS_ADT_URL;#setting-up-the-eclipse-ide'>Setting up the Eclipse IDE</ulink>"
|
||||
section in the Yocto Application Development Toolkit (ADT)
|
||||
User’s Guide for more information.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
@@ -261,13 +268,13 @@
|
||||
<para>
|
||||
The build process is as follows:
|
||||
<orderedlist>
|
||||
<listitem><para>Make sure you have set up the source directory described in the
|
||||
<listitem><para>Make sure you have the Yocto Project files as described in the
|
||||
previous section.</para></listitem>
|
||||
<listitem><para>Initialize the build environment by sourcing a build environment
|
||||
script.</para></listitem>
|
||||
<listitem><para>Optionally ensure the <filename>conf/local.conf</filename> configuration file,
|
||||
<listitem><para>Optionally ensure the <filename>/conf/local.conf</filename> configuration file,
|
||||
which is found in the
|
||||
<link linkend='build-directory'>build directory</link>,
|
||||
<link linkend='yocto-project-build-directory'>Yocto Project Build Directory</link>,
|
||||
is set up how you want it.
|
||||
This file defines many aspects of the build environment including
|
||||
the target machine architecture through the
|
||||
@@ -290,86 +297,20 @@
|
||||
<title>Using Pre-Built Binaries and QEMU</title>
|
||||
|
||||
<para>
|
||||
Another option you have to get started is to use pre-built binaries.
|
||||
The Yocto Project provides many types of binaries with each release.
|
||||
See the <ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Images</ulink>
|
||||
chapter in the Yocto Project Reference Manual
|
||||
for descriptions of the types of binaries that ship with a Yocto Project
|
||||
release.
|
||||
Another option you have to get started is to use pre-built binaries.
|
||||
This scenario is ideal for developing software applications to run on your target hardware.
|
||||
To do this, you need to install the stand-alone Yocto Project cross-toolchain tarball and
|
||||
then download the pre-built kernel that you will boot in the QEMU emulator.
|
||||
Next, you must download and extract the target root filesystem for your target
|
||||
machine’s architecture.
|
||||
Finally, you set up the environment to emulate the hardware and then start the QEMU emulator.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Using a pre-built binary is ideal for developing software applications to run on your
|
||||
target hardware.
|
||||
To do this, you need to be able to access the appropriate cross-toolchain tarball for
|
||||
the architecture on which you are developing.
|
||||
If you are using an SDK type image, the image ships with the complete toolchain native to
|
||||
the architecture.
|
||||
If you are not using an SDK type image, you need to separately download and
|
||||
install the stand-alone Yocto Project cross-toolchain tarball.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Regardless of the type of image you are using, you need to download the pre-built kernel
|
||||
that you will boot in the QEMU emulator and then download and extract the target root
|
||||
filesystem for your target machine’s architecture.
|
||||
You can get architecture-specific binaries and filesystem from
|
||||
<ulink url='&YOCTO_MACHINES_DL_URL;'>machines</ulink>.
|
||||
You can get stand-alone toolchains from
|
||||
<ulink url='&YOCTO_TOOLCHAIN_DL_URL;'>toolchains</ulink>.
|
||||
Once you have all your files, you set up the environment to emulate the hardware
|
||||
by sourcing an environment setup script.
|
||||
Finally, you start the QEMU emulator.
|
||||
You can find details on all these steps in the
|
||||
"<ulink url='&YOCTO_DOCS_QS_URL;#using-pre-built'>Using Pre-Built Binaries and QEMU</ulink>"
|
||||
section of the Yocto Project Quick Start.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Using QEMU to emulate your hardware can result in speed issues
|
||||
depending on the target and host architecture mix.
|
||||
For example, using the <filename>qemux86</filename> image in the emulator
|
||||
on an Intel-based 32-bit (x86) host machine is fast because the target and
|
||||
host architectures match.
|
||||
On the other hand, using the <filename>qemuarm</filename> image on the same Intel-based
|
||||
host can be slower.
|
||||
But, you still achieve faithful emulation of ARM-specific issues.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To speed things up, the QEMU images support using <filename>distcc</filename>
|
||||
to call a cross-compiler outside the emulated system.
|
||||
If you used <filename>runqemu</filename> to start QEMU, and the
|
||||
<filename>distccd</filename> application is present on the host system, any
|
||||
BitBake cross-compiling toolchain available from the build system is automatically
|
||||
used from within QEMU simply by calling <filename>distcc</filename>.
|
||||
You can accomplish this by defining the cross-compiler variable
|
||||
(e.g. <filename>export CC="distcc"</filename>).
|
||||
Alternatively, if you are using a suitable SDK image or the appropriate
|
||||
stand-alone toolchain is present in <filename>/opt/poky</filename>,
|
||||
the toolchain is also automatically used.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
Several mechanisms exist that let you connect to the system running on the
|
||||
QEMU emulator:
|
||||
<itemizedlist>
|
||||
<listitem><para>QEMU provides a framebuffer interface that makes standard
|
||||
consoles available.</para></listitem>
|
||||
<listitem><para>Generally, headless embedded devices have a serial port.
|
||||
If so, you can configure the operating system of the running image
|
||||
to use that port to run a console.
|
||||
The connection uses standard IP networking.</para></listitem>
|
||||
<listitem><para>The QEMU images have a Dropbear secure shell (ssh) server
|
||||
that runs with the root password disabled.
|
||||
This allows you to use standard <filename>ssh</filename> and
|
||||
<filename>scp</filename> commands.</para></listitem>
|
||||
<listitem><para>The QEMU images also contain an embedded Network File
|
||||
System (NFS) server that exports the image's root filesystem.
|
||||
This allows you to make the filesystem available to the
|
||||
host.</para></listitem>
|
||||
</itemizedlist>
|
||||
</note>
|
||||
</section>
|
||||
</chapter>
|
||||
<!--
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<book id='dev-manual' lang='en'
|
||||
<book id='dev-manual' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/dev-title.png'
|
||||
format='SVG'
|
||||
<imagedata fileref='figures/dev-title.png'
|
||||
format='SVG'
|
||||
align='left' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title></title>
|
||||
<title></title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
@@ -40,9 +40,14 @@
|
||||
<revremark>Released with the Yocto Project 1.2 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
<revnumber>1.2.1</revnumber>
|
||||
<date>July 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.2.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.2.2</revnumber>
|
||||
<date>January 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.2.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
@@ -53,15 +58,14 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">
|
||||
Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by
|
||||
Creative Commons.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
Due to production processes, there could be differences between the Yocto Project
|
||||
documentation bundled in the release tarball and
|
||||
documentation bundled in the release tarball and
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;'>
|
||||
The Yocto Project Development Manual</ulink> on
|
||||
the <ulink url='&YOCTO_HOME_URL;'>Yocto Project</ulink> website.
|
||||
@@ -86,6 +90,6 @@
|
||||
<xi:include href="dev-manual-kernel-appendix.xml"/>
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -110,7 +110,7 @@ h5 {
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
<section id='concepts-org'>
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This chapter provides conceptual information about the kernel:
|
||||
This chapter provides conceptual information about the Yocto Project kernel:
|
||||
<itemizedlist>
|
||||
<listitem><para>Kernel Goals</para></listitem>
|
||||
<listitem><para>Kernel Development and Maintenance Overview</para></listitem>
|
||||
<listitem><para>Yocto Project Kernel Development and Maintenance Overview</para></listitem>
|
||||
<listitem><para>Kernel Architecture</para></listitem>
|
||||
<listitem><para>Kernel Tools</para></listitem>
|
||||
</itemizedlist>
|
||||
@@ -25,8 +25,8 @@
|
||||
The complexity of embedded kernel design has increased dramatically.
|
||||
Whether it is managing multiple implementations of a particular feature or tuning and
|
||||
optimizing board specific features, flexibility and maintainability are key concerns.
|
||||
The Linux kernels available through the Yocto Project are presented with the embedded
|
||||
developer's needs in mind and have evolved to assist in these key concerns.
|
||||
The Yocto Project Linux kernel is presented with the embedded
|
||||
developer's needs in mind and has evolved to assist in these key concerns.
|
||||
For example, prior methods such as applying hundreds of patches to an extracted
|
||||
tarball have been replaced with proven techniques that allow easy inspection,
|
||||
bisection and analysis of changes.
|
||||
@@ -34,7 +34,7 @@
|
||||
collaboration with the thousands of upstream development projects.
|
||||
</para>
|
||||
<para>
|
||||
With all these considerations in mind, the Yocto Project's kernel and development team
|
||||
With all these considerations in mind, the Yocto Project kernel and development team
|
||||
strives to attain these goals:
|
||||
<itemizedlist>
|
||||
<listitem><para>Allow the end user to leverage community best practices to seamlessly
|
||||
@@ -63,12 +63,12 @@
|
||||
<section id='kernel-big-picture'>
|
||||
<title>Yocto Project Kernel Development and Maintenance Overview</title>
|
||||
<para>
|
||||
Kernels available through the Yocto Project, like other kernels, are based off the Linux
|
||||
kernel releases from <ulink url='http://www.kernel.org'></ulink>.
|
||||
The Yocto Project kernel, like other kernels, is based off the Linux kernel release
|
||||
from <ulink url='http://www.kernel.org'></ulink>.
|
||||
At the beginning of a major development cycle, the Yocto Project team
|
||||
chooses its kernel based on factors such as release timing, the anticipated release
|
||||
timing of final upstream <filename>kernel.org</filename> versions, and Yocto Project
|
||||
feature requirements.
|
||||
chooses its Yocto Project kernel
|
||||
based on factors like release timing, the anticipated release timing of final
|
||||
upstream <filename>kernel.org</filename> versions, and Yocto Project feature requirements.
|
||||
Typically, the kernel chosen is in the
|
||||
final stages of development by the community.
|
||||
In other words, the kernel is in the release
|
||||
@@ -80,21 +80,21 @@
|
||||
<para>
|
||||
This balance allows the team to deliver the most up-to-date kernel
|
||||
as possible, while still ensuring that the team has a stable official release for
|
||||
the baseline Linux kernel version.
|
||||
the baseline kernel version.
|
||||
</para>
|
||||
<para>
|
||||
The ultimate source for kernels available through the Yocto Project are released kernels
|
||||
The ultimate source for the Yocto Project kernel is a released kernel
|
||||
from <filename>kernel.org</filename>.
|
||||
In addition to a foundational kernel from <filename>kernel.org</filename>, the
|
||||
kernels available through the contain a mix of important new mainline
|
||||
In addition to a foundational kernel from <filename>kernel.org</filename>, the released
|
||||
Yocto Project kernel contains a mix of important new mainline
|
||||
developments, non-mainline developments (when there is no alternative),
|
||||
Board Support Package (BSP) developments,
|
||||
and custom features.
|
||||
These additions result in a commercially released Yocto Project Linux kernel that caters
|
||||
These additions result in a commercially released Yocto Project kernel that caters
|
||||
to specific embedded designer needs for targeted hardware.
|
||||
</para>
|
||||
<para>
|
||||
Once a kernel is officially released, the Yocto Project team goes into
|
||||
Once a Yocto Project kernel is officially released, the Yocto Project team goes into
|
||||
their next development cycle, or upward revision (uprev) cycle, while still
|
||||
continuing maintenance on the released kernel.
|
||||
It is important to note that the most sustainable and stable way
|
||||
@@ -127,8 +127,8 @@
|
||||
These policies result in both a stable and a cutting
|
||||
edge kernel that mixes forward ports of existing features and significant and critical
|
||||
new functionality.
|
||||
Forward porting functionality in the kernels available through the Yocto Project kernel
|
||||
can be thought of as a "micro uprev."
|
||||
Forward porting functionality in the Yocto Project kernel can be thought of as a
|
||||
"micro uprev."
|
||||
The many “micro uprevs” produce a kernel version with a mix of
|
||||
important new mainline, non-mainline, BSP developments and feature integrations.
|
||||
This kernel gives insight into new features and allows focused
|
||||
@@ -142,8 +142,7 @@
|
||||
<section id='kernel-architecture'>
|
||||
<title>Kernel Architecture</title>
|
||||
<para>
|
||||
This section describes the architecture of the kernels available through the
|
||||
Yocto Project and provides information
|
||||
This section describes the architecture of the Yocto Project kernel and provides information
|
||||
on the mechanisms used to achieve that architecture.
|
||||
</para>
|
||||
|
||||
@@ -157,7 +156,7 @@
|
||||
upstream <filename>kernel.org</filename>.
|
||||
</para>
|
||||
<para>
|
||||
You can think of a Yocto Project kernel as consisting of a baseline Linux kernel with
|
||||
You can think of the Yocto Project kernel as consisting of a baseline kernel with
|
||||
added features logically structured on top of the baseline.
|
||||
The features are tagged and organized by way of a branching strategy implemented by the
|
||||
source code manager (SCM) Git.
|
||||
@@ -306,9 +305,9 @@
|
||||
<section id='kernel-configuration'>
|
||||
<title>Kernel Configuration</title>
|
||||
<para>
|
||||
Kernel configuration, along with kernel features, defines how a kernel
|
||||
image is built for the Yocto Project.
|
||||
Through configuration settings, you can customize a Yocto Project kernel to be
|
||||
Kernel configuration, along with kernel features, defines how a Linux Yocto
|
||||
kernel image is built.
|
||||
Through configuration settings, you can customize a Linux Yocto kernel to be
|
||||
specific to particular hardware.
|
||||
For example, you can specify sound support or networking support.
|
||||
This section describes basic concepts behind Kernel configuration within the
|
||||
@@ -317,9 +316,9 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Conceptually, configuration of a Yocto Project kernel occurs similarly to that needed for any
|
||||
Conceptually, Linux Yocto kernel configuration occurs similarly to that needed for any
|
||||
Linux kernel.
|
||||
The build process for a Yocto Project kernel uses a <filename>.config</filename> file, which
|
||||
The Linux Yocto kernel build process uses a <filename>.config</filename> file, which
|
||||
is created through the Linux Kernel Coinfiguration (LKC) tool.
|
||||
You can directly set various configurations in the
|
||||
<filename>.config</filename> file by using the <filename>menuconfig</filename>
|
||||
@@ -353,7 +352,7 @@
|
||||
list of kernel options just as they would appear syntactically in the
|
||||
<filename>.config</filename> file.
|
||||
Configuration fragments are typically logical groupings and are assembled
|
||||
by the OpenEmbedded build system to produce input used by the LKC
|
||||
by the Yocto Project build system to produce input used by the LKC
|
||||
that ultimately generates the <filename>.config</filename> file.</para>
|
||||
<para>The
|
||||
<filename><ulink url='&YOCTO_DOCS_REF_URL;#var-KERNEL_FEATURES'>KERNEL_FEATURES</ulink></filename>
|
||||
@@ -385,6 +384,20 @@
|
||||
with the <filename>kernel.org</filename> history and development.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<!--<para>
|
||||
WRITER NOTE: Put this in for post 1.1 if possible:
|
||||
|
||||
The tools that construct a kernel tree will be discussed later in this
|
||||
document. The following tools form the foundation of the Yocto Project
|
||||
kernel toolkit:
|
||||
<itemizedlist>
|
||||
<listitem><para>git : distributed revision control system created by Linus Torvalds</para></listitem>
|
||||
<listitem><para>guilt: quilt on top of git</para></listitem>
|
||||
<listitem><para>*cfg : kernel configuration management and classification</para></listitem>
|
||||
<listitem><para>kgit*: Yocto Project kernel tree creation and management tools</para></listitem>
|
||||
<listitem><para>scc : series & configuration compiler</para></listitem>
|
||||
</itemizedlist>
|
||||
</para> -->
|
||||
</section>
|
||||
</chapter>
|
||||
<!--
|
||||
|
||||
@@ -9,26 +9,26 @@
|
||||
<section id='book-intro'>
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The Yocto Project presents kernels as a fully patched, history-clean Git
|
||||
repositories.
|
||||
Each repository represents selected features, board support,
|
||||
The Yocto Project presents the kernel as a fully patched, history-clean Git
|
||||
repository.
|
||||
The Git tree represents the selected features, board support,
|
||||
and configurations extensively tested by the Yocto Project.
|
||||
Yocto Project kernels allow the end user to leverage community
|
||||
The Yocto Project kernel allows the end user to leverage community
|
||||
best practices to seamlessly manage the development, build and debug cycles.
|
||||
</para>
|
||||
<para>
|
||||
This manual describes Yocto Project kernels by providing information
|
||||
on history, organization, benefits, and use.
|
||||
This manual describes the Yocto Project kernel by providing information
|
||||
on its history, organization, benefits, and use.
|
||||
The manual consists of two sections:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Concepts:</emphasis> Describes concepts behind a kernel.
|
||||
You will understand how a kernel is organized and why it is organized in
|
||||
the way it is. You will understand the benefits of a kernel's organization
|
||||
<listitem><para><emphasis>Concepts:</emphasis> Describes concepts behind the kernel.
|
||||
You will understand how the kernel is organized and why it is organized in
|
||||
the way it is. You will understand the benefits of the kernel's organization
|
||||
and the mechanisms used to work with the kernel and how to apply it in your
|
||||
design process.</para></listitem>
|
||||
<listitem><para><emphasis>Using a Kernel:</emphasis> Describes best practices
|
||||
<listitem><para><emphasis>Using the Kernel:</emphasis> Describes best practices
|
||||
and "how-to" information
|
||||
that lets you put a kernel to practical use.
|
||||
that lets you put the kernel to practical use.
|
||||
Some examples are how to examine changes in a branch and how to
|
||||
save kernel modifications.</para></listitem>
|
||||
</itemizedlist>
|
||||
@@ -40,7 +40,7 @@
|
||||
<listitem><para>The Linux Foundation's guide for kernel development
|
||||
process - <ulink url='http://ldn.linuxfoundation.org/book/1-a-guide-kernel-development-process'></ulink></para></listitem>
|
||||
<!-- <listitem><para><ulink url='http://userweb.kernel.org/~akpm/stuff/tpp.txt'></ulink></para></listitem> -->
|
||||
<listitem><para>A fairly encompassing guide on Linux kernel development -
|
||||
<listitem><para>A fairly emcompassing guide on Linux kernel development -
|
||||
<ulink url='http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/HOWTO;hb=HEAD'></ulink></para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<section id='actions-org'>
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This chapter describes how to accomplish tasks involving a kernel's tree structure.
|
||||
This chapter describes how to accomplish tasks involving the kernel's tree structure.
|
||||
The information is designed to help the developer that wants to modify the Yocto
|
||||
Project kernel and contribute changes upstream to the Yocto Project.
|
||||
The information covers the following:
|
||||
@@ -25,7 +25,7 @@
|
||||
<section id='tree-construction'>
|
||||
<title>Tree Construction</title>
|
||||
<para>
|
||||
This section describes construction of the Yocto Project kernel source repositories
|
||||
This section describes construction of the Yocto Project kernel repositories
|
||||
as accomplished by the Yocto Project team to create kernel repositories.
|
||||
These kernel repositories are found at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'>&YOCTO_GIT_URL;/cgit.cgi</ulink>
|
||||
@@ -34,35 +34,33 @@
|
||||
compiling and executing the set of feature descriptions for every BSP/feature
|
||||
in the product.
|
||||
Those feature descriptions list all necessary patches,
|
||||
configuration, branching, tagging and feature divisions found in a kernel.
|
||||
configuration, branching, tagging and feature divisions found in the kernel.
|
||||
Thus, the Yocto Project kernel repository (or tree) is built.
|
||||
</para>
|
||||
<para>
|
||||
The existence of this tree allows you to access and clone a particular
|
||||
Yocto Project kernel repository and use it to build images based on their configurations
|
||||
Linux Yocto kernel repository and use it to build images based on their configurations
|
||||
and features.
|
||||
</para>
|
||||
<para>
|
||||
You can find the files used to describe all the valid features and BSPs
|
||||
in the Yocto Project kernel in any clone of the Yocto Project kernel source repository
|
||||
Git tree.
|
||||
in the Yocto Project kernel in any clone of the Linux Yocto kernel source repository Git tree.
|
||||
For example, the following command clones the Yocto Project baseline kernel that
|
||||
branched off of <filename>linux.org</filename> version 3.4:
|
||||
branched off of <filename>linux.org</filename> version 3.0:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/linux-yocto-3.4
|
||||
$ git clone git://git.yoctoproject.org/linux-yocto-3.0
|
||||
</literallayout>
|
||||
For another example of how to set up a local Git repository of the Yocto Project
|
||||
For another example of how to set up a local Git repository of the Linux Yocto
|
||||
kernel files, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#local-kernel-files'>Linux Yocto Kernel</ulink>" bulleted
|
||||
item in The Yocto Project Development Manual.
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#local-kernel-files'>Linux Yocto Kernel</ulink>" bulleted item in The Yocto Project Development Manual.
|
||||
</para>
|
||||
<para>
|
||||
Once you have cloned the kernel Git repository on your local machine, you can
|
||||
switch to the <filename>meta</filename> branch within the repository.
|
||||
Here is an example that assumes the local Git repository for the kernel is in
|
||||
a top-level directory named <filename>linux-yocto-3.4</filename>:
|
||||
a top-level directory named <filename>linux-yocto-3.0</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/linux-yocto-3.4
|
||||
$ cd ~/linux-yocto-3.0
|
||||
$ git checkout -b meta origin/meta
|
||||
</literallayout>
|
||||
Once you have checked out and switched to the <filename>meta</filename> branch,
|
||||
@@ -87,7 +85,7 @@
|
||||
</para>
|
||||
<para>
|
||||
The following steps describe what happens when the Yocto Project Team constructs
|
||||
the Yocto Project kernel source Git repository (or tree) found at
|
||||
the Yocto Linux kernel source Git repository (or tree) found at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink> given the
|
||||
introduction of a new top-level kernel feature or BSP.
|
||||
These are the actions that effectively create the tree
|
||||
@@ -132,7 +130,7 @@
|
||||
</para>
|
||||
<para>
|
||||
The kernel tree is now ready for developer consumption to be locally cloned,
|
||||
configured, and built into a Yocto Project kernel specific to some target hardware.
|
||||
configured, and built into a Linux Yocto kernel specific to some target hardware.
|
||||
<note><para>The generated <filename>meta-*</filename> directories add to the kernel
|
||||
as shipped with the Yocto Project release.
|
||||
Any add-ons and configuration data are applied to the end of an existing branch.
|
||||
@@ -151,7 +149,7 @@
|
||||
<section id='build-strategy'>
|
||||
<title>Build Strategy</title>
|
||||
<para>
|
||||
Once a local Git repository of the Yocto Project kernel exists on a development system,
|
||||
Once a local Git repository of the Linux Yocto kernel exists on a development system,
|
||||
you can consider the compilation phase of kernel development - building a kernel image.
|
||||
Some prerequisites exist that are validated by the build process before compilation
|
||||
starts:
|
||||
@@ -168,7 +166,7 @@
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
The OpenEmbedded build system makes sure these conditions exist before attempting compilation.
|
||||
The Yocto Project makes sure these conditions exist before attempting compilation.
|
||||
Other means, however, do exist, such as as bootstrapping a BSP, see
|
||||
the "<link linkend='workflow-examples'>Workflow Examples</link>".
|
||||
</para>
|
||||
@@ -310,35 +308,32 @@
|
||||
<title>Show a Particular Feature or Branch Change</title>
|
||||
|
||||
<para>
|
||||
Developers use tags in the Yocto Project kernel tree to divide changes for significant
|
||||
features or branches.
|
||||
Once you know a particular tag, you can use Git commands
|
||||
to show changes associated with the tag and find the branches that contain
|
||||
the feature.
|
||||
Significant features or branches are tagged in the Yocto Project tree to divide
|
||||
changes.
|
||||
Remember to first determine (or add) the tag of interest.
|
||||
<note>
|
||||
Because BSP branch, <filename>kernel.org</filename>, and feature tags are all
|
||||
present, there could be many tags.
|
||||
</note>
|
||||
The <filename>git show <tag></filename> command shows changes that are tagged by
|
||||
a feature.
|
||||
Here is an example that shows changes tagged by the <filename>systemtap</filename>
|
||||
feature:
|
||||
<literallayout class='monospaced'>
|
||||
$ git show systemtap
|
||||
</literallayout>
|
||||
You can use the <filename>git branch --contains <tag></filename> command
|
||||
to show the branches that contain a particular feature.
|
||||
This command shows the branches that contain the <filename>systemtap</filename>
|
||||
feature:
|
||||
<literallayout class='monospaced'>
|
||||
$ git branch --contains systemtap
|
||||
# show the changes tagged by a feature
|
||||
> git show <tag>
|
||||
> eg: git show yaffs2
|
||||
|
||||
# determine which branches contain a feature
|
||||
> git branch --contains <tag>
|
||||
|
||||
# show the changes in a kernel type
|
||||
> git whatchanged yocto/base..<kernel type>
|
||||
> eg: git whatchanged yocto/base..yocto/standard/base
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can use many other comparisons to isolate BSP and kernel changes.
|
||||
You can use many other comparisons to isolate BSP changes.
|
||||
For example, you can compare against <filename>kernel.org</filename> tags
|
||||
such as the <filename>v3.4</filename> tag.
|
||||
(e.g. v2.6.27.18, etc), or
|
||||
you can compare against subsystems (e.g. <filename>git whatchanged mm</filename>).
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
@@ -525,7 +520,7 @@
|
||||
"permanent" and you should not modify them.
|
||||
If the commits need to be changed, you can incrementally do so with new commits.
|
||||
These practices follow standard Git workflow and the <filename>kernel.org</filename> best
|
||||
practices, which is recommended.
|
||||
practices, which Yocto Project recommends.
|
||||
<note>
|
||||
It is recommended to tag or branch before adding changes to a Yocto Project
|
||||
BSP or before creating a new one.
|
||||
@@ -603,9 +598,9 @@
|
||||
<para>
|
||||
For example, the following command pushes the changes from your local branch
|
||||
<filename>yocto/standard/common-pc/base</filename> to the remote branch with the same name
|
||||
in the master repository <filename>//git.mycompany.com/pub/git/kernel-3.4</filename>.
|
||||
in the master repository <filename>//git.mycompany.com/pub/git/kernel-3.0</filename>.
|
||||
<literallayout class='monospaced'>
|
||||
> git push ssh://git.mycompany.com/pub/git/kernel-3.4 \
|
||||
> git push ssh://git.mycompany.com/pub/git/kernel-3.0 \
|
||||
yocto/standard/common-pc/base:yocto/standard/common-pc/base
|
||||
</literallayout>
|
||||
</para>
|
||||
@@ -693,7 +688,7 @@
|
||||
However, if the patches are manually applied to a secondary tree and then
|
||||
that tree is checked into the SCM, you can lose change information such as
|
||||
commit logs.
|
||||
This process is not recommended.
|
||||
The Yocto Project does not recommend this process.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -710,14 +705,14 @@
|
||||
<para>
|
||||
This section describes kernel development in an SCM other than Git,
|
||||
which is not the same as exporting changes to another SCM described earlier.
|
||||
For this scenario, you use the OpenEmbedded build system to
|
||||
For this scenario, you use the Yocto Project build system to
|
||||
develop the kernel in a different SCM.
|
||||
The following must be true for you to accomplish this:
|
||||
<itemizedlist>
|
||||
<listitem><para>The delivered Yocto Project kernel must be exported into the second
|
||||
SCM.</para></listitem>
|
||||
<listitem><para>Development must be exported from that secondary SCM into a
|
||||
format that can be used by the OpenEmbedded build system.</para></listitem>
|
||||
format that can be used by the Yocto Project build system.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@@ -793,10 +788,9 @@
|
||||
<para>
|
||||
The basic steps you need to follow are:
|
||||
<orderedlist>
|
||||
<listitem><para><emphasis>Make sure you have set up a local source directory:</emphasis>
|
||||
You must create a local <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source
|
||||
directory</ulink> by either creating a Git repository (recommended) or
|
||||
extracting a Yocto Project release tarball.</para></listitem>
|
||||
<listitem><para><emphasis>Make sure you have the Yocto Project source tree available:</emphasis>
|
||||
You should either create a Yocto Project Git repository (recommended), or
|
||||
you should get the Yocto Project release tarball and extract it.</para></listitem>
|
||||
<listitem><para><emphasis>Choose an existing BSP available with the Yocto Project:</emphasis>
|
||||
Try to map your board features as closely to the features of a BSP that is
|
||||
already supported and exists in the Yocto Project.
|
||||
@@ -806,12 +800,12 @@
|
||||
on the Yocto Project's Download page at
|
||||
<ulink url='&YOCTO_HOME_URL;/download'></ulink>.</para></listitem>
|
||||
<listitem><para><emphasis>Be sure you have the Base BSP:</emphasis>
|
||||
You need to either have a local Git repository of the base BSP set up or
|
||||
have downloaded and extracted the files from a release BSP tarball.
|
||||
You need to either have the Yocto Project Git repository set up or download
|
||||
the tarball of the base BSP.
|
||||
Either method gives you access to the BSP source files.</para></listitem>
|
||||
<listitem><para><emphasis>Make a copy of the existing BSP, thus isolating your new
|
||||
BSP work:</emphasis>
|
||||
Copying the existing BSP file structure gives you a new area in which to work.</para></listitem>
|
||||
Copying the existing BSP structure gives you a new area in which to work.</para></listitem>
|
||||
<listitem><para><emphasis>Make configuration and recipe changes to your new BSP:</emphasis>
|
||||
Configuration changes involve the files in the BSP's <filename>conf</filename>
|
||||
directory.
|
||||
@@ -827,7 +821,7 @@
|
||||
changes to the <filename>local.conf</filename> and <filename>bblayers.conf</filename>
|
||||
files.</para></listitem>
|
||||
<listitem><para><emphasis>Build the image:</emphasis>
|
||||
The OpenEmbedded build system uses BitBake to create the image.
|
||||
The Yocto Project uses the BitBake tool to create the image.
|
||||
You need to decide on the type of image you are going to build (e.g. minimal, base,
|
||||
core, sato, and so forth) and then start the build using the <filename>bitbake</filename>
|
||||
command.</para></listitem>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<book id='kernel-manual' lang='en'
|
||||
<book id='kernel-manual' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/kernel-title.png'
|
||||
format='SVG'
|
||||
<imagedata fileref='figures/kernel-title.png'
|
||||
format='SVG'
|
||||
align='left' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title></title>
|
||||
<title></title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
@@ -55,9 +55,14 @@
|
||||
<revremark>Released with the Yocto Project 1.2 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
<revnumber>1.2.1</revnumber>
|
||||
<date>July 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.2.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.2.2</revnumber>
|
||||
<date>January 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.2.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
@@ -68,12 +73,12 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
</para>
|
||||
<note>
|
||||
Due to production processes, there could be differences between the Yocto Project
|
||||
documentation bundled in the release tarball and
|
||||
documentation bundled in the release tarball and
|
||||
<ulink url='&YOCTO_DOCS_KERNEL_URL;'>
|
||||
The Yocto Project Kernel Architecture and Use Manual</ulink> on
|
||||
the <ulink url='&YOCTO_HOME_URL;'>Yocto Project</ulink> website.
|
||||
@@ -95,6 +100,6 @@
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -110,7 +110,7 @@ h5 {
|
||||
h6 {
|
||||
margin: 1em 0em 0em 0em;
|
||||
padding: 1em 0em 0em 0em;
|
||||
font-size: 110%;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
803
documentation/poky-ref-manual/development.xml
Normal file
803
documentation/poky-ref-manual/development.xml
Normal file
@@ -0,0 +1,803 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id="platdev">
|
||||
<title>Platform Development with the Yocto Project</title>
|
||||
|
||||
<section id="platdev-appdev">
|
||||
<title>Application Development Using the Yocto Project</title>
|
||||
<para>
|
||||
The Yocto Project supports several methods of application development through which
|
||||
you can create user-space software designed to run on an embedded device that uses
|
||||
a Linux Yocto image developed with the Yocto Project.
|
||||
This flexibility allows you to choose the method that works best for you.
|
||||
This chapter describes each development method.
|
||||
</para>
|
||||
|
||||
<section id="platdev-appdev-external-sdk">
|
||||
<title>External Development Using the Meta-Toolchain</title>
|
||||
<para>
|
||||
The Yocto Project provides toolchains that allow you to develop your application
|
||||
outside of the Yocto Project build system for specific hardware.
|
||||
These toolchains (called meta-toolchains) contain cross-development tools such as compilers,
|
||||
linkers, and debuggers that build your application for your target device.
|
||||
The Yocto Project also provides images that have toolchains for supported
|
||||
architectures included within the image.
|
||||
This allows you to compile, debug, or profile applications directly on the target device.
|
||||
See the
|
||||
"<link linkend='ref-images'>Reference: Images</link>" appendix for a listing of the image
|
||||
types that Yocto Project supports.
|
||||
</para>
|
||||
<para>
|
||||
Using the BitBake tool you can build a meta-toolchain or meta-toolchain-sdk target,
|
||||
which generates a tarball.
|
||||
Unpacking this tarball into the <filename class="directory">/opt/poky</filename> directory
|
||||
on your host produces a setup script
|
||||
(e.g. <filename>/opt/poky/environment-setup-i586-poky-linux</filename>) that
|
||||
you can <filename>source</filename> to initialize your build environment.
|
||||
Sourcing this script adds the compiler, QEMU scripts, QEMU binary, a special version of
|
||||
<filename>pkgconfig</filename> and other
|
||||
useful utilities to the <filename>PATH</filename> variable used by the Yocto Project
|
||||
build environment.
|
||||
Variables to assist <filename>pkgconfig</filename> and
|
||||
Autotools are also defined so that, for example, <filename>configure</filename>
|
||||
can find pre-generated test results for tests that need target hardware on which to run.
|
||||
</para>
|
||||
<para>
|
||||
Using the toolchain with Autotool-enabled packages is straightforward - just pass the
|
||||
appropriate <filename>host</filename> option to <filename>configure</filename>.
|
||||
Following is an example:
|
||||
<literallayout class='monospaced'>
|
||||
$ ./configure --host=arm-poky-linux-gnueabi
|
||||
</literallayout>
|
||||
For projects that are not Autotool-enabled, it is usually just a case of ensuring
|
||||
you point to and use the cross-toolchain.
|
||||
For example, the following two lines of code in a <filename>Makefile</filename>
|
||||
that builds your application
|
||||
specify to use the cross-compiler <filename>arm-poky-linux-gnueabi-gcc</filename>
|
||||
and linker <filename>arm-poky-linux-gnueabi-ld</filename>, which are part of the
|
||||
meta-toolchain you would have previously established:
|
||||
<literallayout class='monospaced'>
|
||||
CC=arm-poky-linux-gnueabi-gcc;
|
||||
LD=arm-poky-linux-gnueabi-ld;
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="using-the-eclipse-and-anjuta-plug-ins">
|
||||
<title>External Development Using the Eclipse Plug-in</title>
|
||||
<para>
|
||||
The current release of the Yocto Project supports the Eclipse IDE plug-in
|
||||
to make developing software easier for the application developer.
|
||||
The plug-in provides capability extensions to the graphical IDE to allow
|
||||
for cross compilation, deployment and execution of the application within a QEMU
|
||||
emulation session.
|
||||
Support of the Eclipse plug-in also allows for cross debugging and
|
||||
profiling.
|
||||
Additionally, the Eclipse plug-in provides a suite of tools
|
||||
that allows the developer to perform remote profiling, tracing, collection of
|
||||
power consumption data, collection of latency data and collection of performance data.
|
||||
</para>
|
||||
<note>
|
||||
The current release of the Yocto Project no longer supports the Anjuta plug-in.
|
||||
However, the Poky Anjuta Plug-in is available to download directly from the Poky
|
||||
Git repository located through the web interface at
|
||||
<ulink url='&YOCTO_GIT_URL;'></ulink> under IDE Plugins.
|
||||
The community is free to continue supporting it beyond the Yocto Project 0.9
|
||||
Release.
|
||||
</note>
|
||||
<para>
|
||||
To use the Eclipse plug-in you need the Eclipse Framework (Helios 3.6.1) along
|
||||
with other plug-ins installed into the Eclipse IDE.
|
||||
Once you have your environment setup you need to configure the Eclipse plug-in.
|
||||
For information on how to install and configure the Eclipse plug-in, see the
|
||||
"<ulink url='&YOCTO_DOCS_ADT_URL;#adt-eclipse'>Working Within Eclipse</ulink>"
|
||||
chapter in the Yocto Project Application Development Toolkit (ADT) User's Guide.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-appdev-qemu">
|
||||
<title>External Development Using the QEMU Emulator</title>
|
||||
<para>
|
||||
Running Poky QEMU images is covered in the
|
||||
"<ulink url='&YOCTO_DOCS_QS_URL;#test-run'>A Quick Test Run</ulink>"
|
||||
section of the Yocto Project Quick Start.
|
||||
</para>
|
||||
<para>
|
||||
The QEMU images shipped with the Yocto Project contain complete toolchains
|
||||
native to their target architectures.
|
||||
This support allows you to develop applications within QEMU similar to the way
|
||||
you would using a normal host development system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Speed can be an issue depending on the target and host architecture mix.
|
||||
For example, using the <filename>qemux86</filename> image in the emulator
|
||||
on an Intel-based 32-bit (x86) host machine is fast because the target and
|
||||
host architectures match.
|
||||
On the other hand, using the <filename>qemuarm</filename> image on the same Intel-based
|
||||
host can be slower.
|
||||
But, you still achieve faithful emulation of ARM-specific issues.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To speed things up, the QEMU images support using <filename>distcc</filename>
|
||||
to call a cross-compiler outside the emulated system.
|
||||
If you used <filename>runqemu</filename> to start QEMU, and
|
||||
<filename>distccd</filename> is present on the host system, any BitBake cross-compiling
|
||||
toolchain available from the build system is automatically
|
||||
used from within QEMU simply by calling <filename>distcc</filename>.
|
||||
You can accomplish this by defining the cross-compiler variable
|
||||
(e.g. <filename>export CC="distcc"</filename>).
|
||||
Alternatively, if a suitable SDK/toolchain is present in
|
||||
<filename>/opt/poky</filename> the toolchain is also automatically used.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Several mechanisms exist that let you connect to the system running on the
|
||||
QEMU emulator:
|
||||
<itemizedlist>
|
||||
<listitem><para>QEMU provides a framebuffer interface that makes standard
|
||||
consoles available.</para></listitem>
|
||||
<listitem><para>Generally, headless embedded devices have a serial port.
|
||||
If so, you can configure the operating system of the running image
|
||||
to use that port to run a console.
|
||||
The connection uses standard IP networking.</para></listitem>
|
||||
<listitem><para>The QEMU images have a Dropbear secure shell (ssh) server
|
||||
that runs with the root password disabled.
|
||||
This allows you to use standard <filename>ssh</filename> and
|
||||
<filename>scp</filename> commands.</para></listitem>
|
||||
<listitem><para>The QEMU images also contain an embedded Network Files
|
||||
System (NFS) server that exports the image's root filesystem.
|
||||
This allows you to make the filesystem available to the
|
||||
host.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-appdev-insitu">
|
||||
<title>Development Using Yocto Project Directly</title>
|
||||
<para>
|
||||
Working directly with the Yocto Project is a fast and effective development technique.
|
||||
The idea is that you can directly edit files in a working directory
|
||||
(<filename><link linkend='var-WORKDIR'>WORKDIR</link></filename>)
|
||||
or the source directory (<filename><link linkend='var-S'>S</link></filename>)
|
||||
and then force specific tasks to rerun in order to test the changes.
|
||||
An example session working on the matchbox-desktop package might
|
||||
look like this:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake matchbox-desktop
|
||||
$ sh
|
||||
$ cd tmp/work/armv5te-poky-linux-gnueabi/matchbox-desktop-2.0+svnr1708-r0/
|
||||
$ cd matchbox-desktop-2
|
||||
$ vi src/main.c
|
||||
.
|
||||
.
|
||||
[Make your changes]
|
||||
.
|
||||
.
|
||||
$ exit
|
||||
$ bitbake matchbox-desktop -c compile -f
|
||||
$ bitbake matchbox-desktop
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This example builds the <filename>matchbox-desktop</filename> package,
|
||||
creates a new terminal, changes into the work directory for the package,
|
||||
changes a file, exits out of the terminal, and then recompiles the
|
||||
package.
|
||||
Instead of using <filename>sh</filename>,
|
||||
you can also use two different terminals.
|
||||
However, the risk of using two terminals is that a command like
|
||||
<filename>unpack</filename> could destroy your changes in the
|
||||
work directory.
|
||||
Consequently, you need to work carefully.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is useful when making changes directly to the work directory files to do
|
||||
so using the Quilt tool as detailed in the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#using-a-quilt-workflow'>Using a Quilt Workflow</ulink>" section in the Yocto Project Development Manual.
|
||||
Using Quilt, you can copy patches into the recipe directory and use the patches directly
|
||||
through use of the <filename><link linkend='var-SRC_URI'>SRC_URI</link></filename> variable.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For a review of the skills used in this section, see the
|
||||
"<link linkend='usingpoky-components-bitbake'>BitBake</link>" and
|
||||
"<link linkend='usingpoky-debugging-taskrunning'>Running Specific Tasks</link>" sections.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-appdev-devshell">
|
||||
<title>Development Within a Development Shell</title>
|
||||
|
||||
<para>
|
||||
When debugging certain commands or even when just editing packages,
|
||||
<filename>devshell</filename> can be a useful tool.
|
||||
Using <filename>devshell</filename> differs from the example shown in the previous
|
||||
section in that when you invoke <filename>devshell</filename> source files are
|
||||
extracted into your working directory and patches are applied.
|
||||
Then, a new terminal is opened and you are placed in the working directory.
|
||||
In the new terminal all the Yocto Project build-related environment variables are
|
||||
still defined so you can use commands such as <filename>configure</filename> and
|
||||
<filename>make</filename>.
|
||||
The commands execute just as if the Yocto Project build system were executing them.
|
||||
Consequently, working this way can be helpful when debugging a build or preparing
|
||||
software to be used with the Yocto Project build system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Following is an example that uses <filename>devshell</filename> on a target named
|
||||
<filename>matchbox-desktop</filename>:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake matchbox-desktop -c devshell
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This command opens a terminal with a shell prompt within the Poky
|
||||
environment.
|
||||
The following occurs:
|
||||
<itemizedlist>
|
||||
<listitem><para>The <filename>PATH</filename> variable includes the
|
||||
cross-toolchain.</para></listitem>
|
||||
<listitem><para>The <filename>pkgconfig</filename> variables find the correct
|
||||
<filename>.pc</filename> files.</para></listitem>
|
||||
<listitem><para>The <filename>configure</filename> command finds the
|
||||
Yocto Project site files as well as any other necessary files.</para></listitem>
|
||||
</itemizedlist>
|
||||
Within this environment, you can run <filename>configure</filename>
|
||||
or <filename>compile</filename> commands as if they were being run by
|
||||
the Yocto Project build system itself.
|
||||
As noted earlier, the working directory also automatically changes to the
|
||||
source directory (<filename><link linkend='var-S'>S</link></filename>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you are finished, you just exit the shell or close the terminal window.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The default shell used by <filename>devshell</filename> is xterm.
|
||||
For examples of available options, see the "UI/Interaction Configuration"
|
||||
section of the
|
||||
<filename>meta/conf/bitbake.conf</filename> configuration file in the Yocto Project
|
||||
files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Because an external shell is launched rather than opening directly into the
|
||||
original terminal window, it allows easier interaction with BitBake's multiple
|
||||
threads as well as accomodates a future client/server split.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>It is worth remembering that when using <filename>devshell</filename>
|
||||
you need to use the full compiler name such as <filename>arm-poky-linux-gnueabi-gcc</filename>
|
||||
instead of just using <filename>gcc</filename>.
|
||||
The same applies to other applications such as <filename>binutils</filename>,
|
||||
<filename>libtool</filename> and so forth.
|
||||
BitBake sets up environment variables such as <filename>CC</filename>
|
||||
to assist applications, such as <filename>make</filename> to find the correct tools.</para>
|
||||
<para>It is also worth noting that <filename>devshell</filename> still works over
|
||||
X11 forwarding and similar situations</para>
|
||||
</note>
|
||||
</section>
|
||||
|
||||
<section id="platdev-appdev-srcrev">
|
||||
<title>Development Within Yocto Project for a Package that Uses an External SCM</title>
|
||||
|
||||
<para>
|
||||
If you're working on a recipe that pulls from an external Source Code Manager (SCM), it
|
||||
is possible to have the Yocto Project build system notice new changes added to the
|
||||
SCM and then build the package that depends on them using the latest version.
|
||||
This only works for SCMs from which it is possible to get a sensible revision number for changes.
|
||||
Currently, you can do this with Apache Subversion (SVN), Git, and Bazaar (BZR) repositories.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To enable this behavior, simply add the following to the <filename>local.conf</filename>
|
||||
configuration file in the build directory of the Yocto Project files:
|
||||
<literallayout class='monospaced'>
|
||||
SRCREV_pn-<PN> = "${AUTOREV}"
|
||||
</literallayout>
|
||||
where <filename>PN</filename>
|
||||
is the name of the package for which you want to enable automatic source
|
||||
revision updating.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="platdev-gdb-remotedebug">
|
||||
<title>Debugging With the GNU Project Debugger (GDB) Remotely</title>
|
||||
|
||||
<para>
|
||||
GDB allows you to examine running programs, which in turn help you to understand and fix problems.
|
||||
It also allows you to perform post-mortem style analysis of program crashes.
|
||||
GDB is available as a package within the Yocto Project and by default is
|
||||
installed in sdk images.
|
||||
See the "<link linkend='ref-images'>Reference: Images</link>" appendix for a description of these
|
||||
images.
|
||||
You can find information on GDB at <ulink url="http://sourceware.org/gdb/"/>.
|
||||
</para>
|
||||
|
||||
<tip>
|
||||
For best results, install <filename>-dbg</filename> packages for the applications
|
||||
you are going to debug.
|
||||
Doing so makes available extra debug symbols that give you more meaningful output.
|
||||
</tip>
|
||||
|
||||
<para>
|
||||
Sometimes, due to memory or disk space constraints, it is not possible
|
||||
to use GDB directly on the remote target to debug applications.
|
||||
These constraints arise because GDB needs to load the debugging information and the
|
||||
binaries of the process being debugged.
|
||||
Additionally, GDB needs to perform many computations to locate information such as function
|
||||
names, variable names and values, stack traces and so forth - even before starting the
|
||||
debugging process.
|
||||
These extra computations place more load on the target system and can alter the
|
||||
characteristics of the program being debugged.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To help get past the previously mentioned constraints, you can use Gdbserver.
|
||||
Gdbserver runs on the remote target and does not load any debugging information
|
||||
from the debugged process.
|
||||
Instead, a GDB instance processes the debugging information that is run on a
|
||||
remote computer - the host GDB.
|
||||
The host GDB then sends control commands to Gdbserver to make it stop or start the debugged
|
||||
program, as well as read or write memory regions of that debugged program.
|
||||
All the debugging information loaded and processed as well
|
||||
as all the heavy debugging is done by the host GDB.
|
||||
Offloading these processes gives the Gdbserver running on the target a chance to remain
|
||||
small and fast.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Because the host GDB is responsible for loading the debugging information and
|
||||
for doing the necessary processing to make actual debugging happen, the
|
||||
user has to make sure the host can access the unstripped binaries complete
|
||||
with their debugging information and also be sure the target is compiled with no optimizations.
|
||||
The host GDB must also have local access to all the libraries used by the
|
||||
debugged program.
|
||||
Because Gdbserver does not need any local debugging information, the binaries on
|
||||
the remote target can remain stripped.
|
||||
However, the binaries must also be compiled without optimization
|
||||
so they match the host's binaries.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To remain consistent with GDB documentation and terminology, the binary being debugged
|
||||
on the remote target machine is referred to as the "inferior" binary.
|
||||
For documentation on GDB see the
|
||||
<ulink url="http://sourceware.org/gdb/documentation/">GDB site</ulink>.
|
||||
</para>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdbserver">
|
||||
<title>Launching Gdbserver on the Target</title>
|
||||
|
||||
<para>
|
||||
First, make sure Gdbserver is installed on the target.
|
||||
If it is not, install the package <filename>gdbserver</filename>, which needs the
|
||||
<filename>libthread-db1</filename> package.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
As an example, to launch Gdbserver on the target and make it ready to "debug" a
|
||||
program located at <filename>/path/to/inferior</filename>, connect
|
||||
to the target and launch:
|
||||
<literallayout class='monospaced'>
|
||||
$ gdbserver localhost:2345 /path/to/inferior
|
||||
</literallayout>
|
||||
Gdbserver should now be listening on port 2345 for debugging
|
||||
commands coming from a remote GDB process that is running on the host computer.
|
||||
Communication between Gdbserver and the host GDB are done using TCP.
|
||||
To use other communication protocols, please refer to the
|
||||
<ulink url='http://www.gnu.org/software/gdb/'>Gdbserver documentation</ulink>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdb">
|
||||
<title>Launching GDB on the Host Computer</title>
|
||||
|
||||
<para>
|
||||
Running GDB on the host computer takes a number of stages.
|
||||
This section describes those stages.
|
||||
</para>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdb-buildcross">
|
||||
<title>Building the Cross-GDB Package</title>
|
||||
<para>
|
||||
A suitable GDB cross-binary is required that runs on your host computer but
|
||||
also knows about the the ABI of the remote target.
|
||||
You can get this binary from the the Yocto Project meta-toolchain.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
/usr/local/poky/eabi-glibc/arm/bin/arm-poky-linux-gnueabi-gdb
|
||||
</literallayout>
|
||||
where <filename>arm</filename> is the target architecture and
|
||||
<filename>linux-gnueabi</filename> the target ABI.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Alternatively, the Yocto Project can build the <filename>gdb-cross</filename> binary.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake gdb-cross
|
||||
</literallayout>
|
||||
Once the binary is built, you can find it here:
|
||||
<literallayout class='monospaced'>
|
||||
tmp/sysroots/<host-arch>/usr/bin/<target-abi>-gdb
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdb-inferiorbins">
|
||||
<title>Making the Inferior Binaries Available</title>
|
||||
|
||||
<para>
|
||||
The inferior binary (complete with all debugging symbols) as well as any
|
||||
libraries (and their debugging symbols) on which the inferior binary depends
|
||||
need to be available.
|
||||
There are a number of ways you can make these available.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Perhaps the easiest way is to have an 'sdk' image that corresponds to the plain
|
||||
image installed on the device.
|
||||
In the case of <filename>core-image-sato</filename>,
|
||||
<filename>core-image-sdk</filename> would contain suitable symbols.
|
||||
Because the sdk images already have the debugging symbols installed, it is just a
|
||||
question of expanding the archive to some location and then informing GDB.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Alternatively, Yocto Project can build a custom directory of files for a specific
|
||||
debugging purpose by reusing its <filename>tmp/rootfs</filename> directory.
|
||||
This directory contains the contents of the last built image.
|
||||
This process assumes two things:
|
||||
<itemizedlist>
|
||||
<listitem><para>The image running on the target was the last image to
|
||||
be built by the Yocto Project.</para></listitem>
|
||||
<listitem><para>The package (<filename>foo</filename> in the following
|
||||
example) that contains the inferior binary to be debugged has been built
|
||||
without optimization and has debugging information available.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following steps show how to build the custom directory of files:
|
||||
<orderedlist>
|
||||
<listitem><para>Install the package (<filename>foo</filename> in this case) to
|
||||
<filename>tmp/rootfs</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
|
||||
tmp/work/<target-abi>/core-image-sato-1.0-r0/temp/opkg.conf -o \
|
||||
tmp/rootfs/ update
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Install the debugging information:
|
||||
<literallayout class='monospaced'>
|
||||
$ tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
|
||||
tmp/work/<target-abi>/core-image-sato-1.0-r0/temp/opkg.conf \
|
||||
-o tmp/rootfs install foo
|
||||
|
||||
$ tmp/sysroots/i686-linux/usr/bin/opkg-cl -f \
|
||||
tmp/work/<target-abi>/core-image-sato-1.0-r0/temp/opkg.conf \
|
||||
-o tmp/rootfs install foo-dbg
|
||||
</literallayout></para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdb-launchhost">
|
||||
<title>Launch the Host GDB</title>
|
||||
|
||||
<para>
|
||||
To launch the host GDB, you run the <filename>cross-gdb</filename> binary and provide
|
||||
the inferior binary as part of the command line.
|
||||
For example, the following command form continues with the example used in
|
||||
the previous section.
|
||||
This command form loads the <filename>foo</filename> binary
|
||||
as well as the debugging information:
|
||||
<literallayout class='monospaced'>
|
||||
$ <target-abi>-gdb rootfs/usr/bin/foo
|
||||
</literallayout>
|
||||
Once the GDB prompt appears, you must instruct GDB to load all the libraries
|
||||
of the inferior binary from <filename>tmp/rootfs</filename> as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ set solib-absolute-prefix /path/to/tmp/rootfs
|
||||
</literallayout>
|
||||
The pathname <filename>/path/to/tmp/rootfs</filename> must either be
|
||||
the absolute path to <filename>tmp/rootfs</filename> or the location at which
|
||||
binaries with debugging information reside.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At this point you can have GDB connect to the Gdbserver that is running
|
||||
on the remote target by using the following command form:
|
||||
<literallayout class='monospaced'>
|
||||
$ target remote remote-target-ip-address:2345
|
||||
</literallayout>
|
||||
The <filename>remote-target-ip-address</filename> is the IP address of the
|
||||
remote target where the Gdbserver is running.
|
||||
Port 2345 is the port on which the GDBSERVER is running.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-gdb-remotedebug-launch-gdb-using">
|
||||
<title>Using the Debugger</title>
|
||||
|
||||
<para>
|
||||
You can now proceed with debugging as normal - as if you were debugging
|
||||
on the local machine.
|
||||
For example, to instruct GDB to break in the "main" function and then
|
||||
continue with execution of the inferior binary use the following commands
|
||||
from within GDB:
|
||||
<literallayout class='monospaced'>
|
||||
(gdb) break main
|
||||
(gdb) continue
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more information about using GDB, see the project's online documentation at
|
||||
<ulink url="http://sourceware.org/gdb/download/onlinedocs/"/>.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="platdev-oprofile">
|
||||
<title>Profiling with OProfile</title>
|
||||
|
||||
<para>
|
||||
<ulink url="http://oprofile.sourceforge.net/">OProfile</ulink> is a
|
||||
statistical profiler well suited for finding performance
|
||||
bottlenecks in both userspace software and in the kernel.
|
||||
This profiler provides answers to questions like "Which functions does my application spend
|
||||
the most time in when doing X?"
|
||||
Because the Yocto Project is well integrated with OProfile, it makes profiling applications on target
|
||||
hardware straightforward.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To use OProfile, you need an image that has OProfile installed.
|
||||
The easiest way to do this is with <filename>tools-profile</filename> in the
|
||||
<filename><link linkend='var-IMAGE_FEATURES'>IMAGE_FEATURES</link></filename> variable.
|
||||
You also need debugging symbols to be available on the system where the analysis
|
||||
takes place.
|
||||
You can gain access to the symbols by using <filename>dbg-pkgs</filename> in the
|
||||
<filename>IMAGE_FEATURES</filename> variable or by
|
||||
installing the appropriate <filename>-dbg</filename> packages.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For successful call graph analysis, the binaries must preserve the frame
|
||||
pointer register and should also be compiled with the
|
||||
<filename>-fno-omit-framepointer</filename> flag.
|
||||
In the Yocto Project you can achieve this by setting the
|
||||
<filename><link linkend='var-SELECTED_OPTIMIZATION'>SELECTED_OPTIMIZATION
|
||||
</link></filename> variable to
|
||||
<filename>-fexpensive-optimizations -fno-omit-framepointer -frename-registers -O2</filename>.
|
||||
You can also achieve it by setting the
|
||||
<filename><link linkend='var-DEBUG_BUILD'>DEBUG_BUILD</link></filename> variable to "1" in
|
||||
the <filename>local.conf</filename> configuration file.
|
||||
If you use the <filename>DEBUG_BUILD</filename> variable you will also add extra debug information
|
||||
that can make the debug packages large.
|
||||
</para>
|
||||
|
||||
<section id="platdev-oprofile-target">
|
||||
<title>Profiling on the Target</title>
|
||||
|
||||
<para>
|
||||
Using OProfile you can perform all the profiling work on the target device.
|
||||
A simple OProfile session might look like the following:
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literallayout class='monospaced'>
|
||||
# opcontrol --reset
|
||||
# opcontrol --start --separate=lib --no-vmlinux -c 5
|
||||
.
|
||||
.
|
||||
[do whatever is being profiled]
|
||||
.
|
||||
.
|
||||
# opcontrol --stop
|
||||
$ opreport -cl
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In this example, the <filename>reset</filename> command clears any previously profiled data.
|
||||
The next command starts OProfile.
|
||||
The options used when starting the profiler separate dynamic library data
|
||||
within applications, disable kernel profiling, and enable callgraphing up to
|
||||
five levels deep.
|
||||
<note>
|
||||
To profile the kernel, you would specify the
|
||||
<filename>--vmlinux=/path/to/vmlinux</filename> option.
|
||||
The <filename>vmlinux</filename> file is usually in the Yocto Project file's
|
||||
<filename>/boot/</filename> directory and must match the running kernel.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After you perform your profiling tasks, the next command stops the profiler.
|
||||
After that, you can view results with the <filename>opreport</filename> command with options
|
||||
to see the separate library symbols and callgraph information.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Callgraphing logs information about time spent in functions and about a function's
|
||||
calling function (parent) and called functions (children).
|
||||
The higher the callgraphing depth, the more accurate the results.
|
||||
However, higher depths also increase the logging overhead.
|
||||
Consequently, you should take care when setting the callgraphing depth.
|
||||
<note>
|
||||
On ARM, binaries need to have the frame pointer enabled for callgraphing to work.
|
||||
To accomplish this use the <filename>-fno-omit-framepointer</filename> option
|
||||
with <filename>gcc</filename>.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more information on using OProfile, see the OProfile
|
||||
online documentation at
|
||||
<ulink url="http://oprofile.sourceforge.net/docs/"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-oprofile-oprofileui">
|
||||
<title>Using OProfileUI</title>
|
||||
|
||||
<para>
|
||||
A graphical user interface for OProfile is also available.
|
||||
You can download and build this interface from the Yocto Project at
|
||||
<ulink url="&YOCTO_GIT_URL;/cgit.cgi/oprofileui/"></ulink>.
|
||||
If the "tools-profile" image feature is selected, all necessary binaries
|
||||
are installed onto the target device for OProfileUI interaction.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Even though the Yocto Project usually includes all needed patches on the target device, you
|
||||
might find you need other OProfile patches for recent OProfileUI features.
|
||||
If so, see the <ulink url='&YOCTO_GIT_URL;/cgit.cgi/oprofileui/tree/README'>
|
||||
OProfileUI README</ulink> for the most recent information.
|
||||
</para>
|
||||
|
||||
<section id="platdev-oprofile-oprofileui-online">
|
||||
<title>Online Mode</title>
|
||||
|
||||
<para>
|
||||
Using OProfile in online mode assumes a working network connection with the target
|
||||
hardware.
|
||||
With this connection, you just need to run "oprofile-server" on the device.
|
||||
By default, OProfile listens on port 4224.
|
||||
<note>
|
||||
You can change the port using the <filename>--port</filename> command-line
|
||||
option.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The client program is called <filename>oprofile-viewer</filename> and its UI is relatively
|
||||
straightforward.
|
||||
You access key functionality through the buttons on the toolbar, which
|
||||
are duplicated in the menus.
|
||||
Here are the buttons:
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Connect:</emphasis> Connects to the remote host.
|
||||
You can also supply the IP address or hostname.</para></listitem>
|
||||
<listitem><para><emphasis>Disconnect:</emphasis> Disconnects from the target.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Start:</emphasis> Starts profiling on the device.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Stop:</emphasis> Stops profiling on the device and
|
||||
downloads the data to the local host.
|
||||
Stopping the profiler generates the profile and displays it in the viewer.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Download:</emphasis> Downloads the data from the
|
||||
target and generates the profile, which appears in the viewer.</para></listitem>
|
||||
<listitem><para><emphasis>Reset:</emphasis> Resets the sample data on the device.
|
||||
Resetting the data removes sample information collected from previous
|
||||
sampling runs.
|
||||
Be sure you reset the data if you do not want to include old sample information.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>Save:</emphasis> Saves the data downloaded from the
|
||||
target to another directory for later examination.</para></listitem>
|
||||
<listitem><para><emphasis>Open:</emphasis> Loads previously saved data.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The client downloads the complete 'profile archive' from
|
||||
the target to the host for processing.
|
||||
This archive is a directory that contains the sample data, the object files,
|
||||
and the debug information for the object files.
|
||||
The archive is then converted using the <filename>oparchconv</filename> script, which is
|
||||
included in this distribution.
|
||||
The script uses <filename>opimport</filename> to convert the archive from
|
||||
the target to something that can be processed on the host.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Downloaded archives reside in the Yocto Project's build directory in
|
||||
<filename>/tmp</filename> and are cleared up when they are no longer in use.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you wish to perform kernel profiling, you need to be sure
|
||||
a <filename>vmlinux</filename> file that matches the running kernel is available.
|
||||
In the Yocto Project, that file is usually located in
|
||||
<filename>/boot/vmlinux-KERNELVERSION</filename>, where
|
||||
<filename>KERNEL-version</filename> is the version of the kernel.
|
||||
The Yocto Project generates separate <filename>vmlinux</filename> packages for each kernel
|
||||
it builds.
|
||||
Thus, it should just be a question of making sure a matching package is
|
||||
installed (e.g. <filename>opkg install kernel-vmlinux</filename>.
|
||||
The files are automatically installed into development and profiling images
|
||||
alongside OProfile.
|
||||
A configuration option exists within the OProfileUI settings page that you can use to
|
||||
enter the location of the <filename>vmlinux</filename> file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Waiting for debug symbols to transfer from the device can be slow, and it
|
||||
is not always necessary to actually have them on the device for OProfile use.
|
||||
All that is needed is a copy of the filesystem with the debug symbols present
|
||||
on the viewer system.
|
||||
The "<link linkend='platdev-gdb-remotedebug-launch-gdb'>Launching GDB on the Host Computer</link>"
|
||||
section covers how to create such a directory with
|
||||
the Yocto Project and how to use the OProfileUI Settings dialog to specify the location.
|
||||
If you specify the directory, it will be used when the file checksums
|
||||
match those on the system you are profiling.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="platdev-oprofile-oprofileui-offline">
|
||||
<title>Offline Mode</title>
|
||||
|
||||
<para>
|
||||
If network access to the target is unavailable, you can generate
|
||||
an archive for processing in <filename>oprofile-viewer</filename> as follows:
|
||||
<literallayout class='monospaced'>
|
||||
# opcontrol --reset
|
||||
# opcontrol --start --separate=lib --no-vmlinux -c 5
|
||||
.
|
||||
.
|
||||
[do whatever is being profiled]
|
||||
.
|
||||
.
|
||||
# opcontrol --stop
|
||||
# oparchive -o my_archive
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In the above example, <filename>my_archive</filename> is the name of the
|
||||
archive directory where you would like the profile archive to be kept.
|
||||
After the directory is created, you can copy it to another host and load it
|
||||
using <filename>oprofile-viewer</filename> open functionality.
|
||||
If necessary, the archive is converted.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</chapter>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
@@ -1,8 +1,8 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='faq'>
|
||||
<appendix id='faq'>
|
||||
<title>FAQ</title>
|
||||
<qandaset>
|
||||
<qandaentry>
|
||||
@@ -13,17 +13,11 @@
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
The term "Poky" is sometimes used to refer to the build system that the
|
||||
Yocto Project uses.
|
||||
The build system used in the Yocto project is referred to as the
|
||||
OpenEmbedded build system because "Poky" was derived from <ulink
|
||||
Poky is the Yocto Project build system that was derived from <ulink
|
||||
url='&OE_HOME_URL;'>OpenEmbedded</ulink>.
|
||||
Poky is a stable, smaller subset focused on the mobile environment.
|
||||
Development in the Yocto Project using Poky is closely tied to OpenEmbedded with
|
||||
features being merged regularly between the two for mutual benefit.
|
||||
For a fuller description of the term "Poky", see the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#poky'>poky</ulink> term in the Yocto Project
|
||||
Development Manual.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
@@ -70,8 +64,7 @@
|
||||
<para>
|
||||
There are three areas that help with stability;
|
||||
<itemizedlist>
|
||||
<listitem><para>The Yocto Project team keeps
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#poky'>Poky</ulink> small and focused.
|
||||
<listitem><para>The Yocto Project team keeps Poky small and focused.
|
||||
It contains around 650 packages as compared to over 5000 for full
|
||||
OpenEmbedded.</para></listitem>
|
||||
<listitem><para>The Yocto Project only supports hardware that the
|
||||
@@ -107,17 +100,16 @@
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>
|
||||
Are there any products using the OpenEmbedded build system (poky)?
|
||||
Are there any products using Poky?
|
||||
</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
The <ulink url='http://vernier.com/labquest/'>Vernier LabQuest</ulink> is using
|
||||
the OpenEmbedded build system.
|
||||
the Yocto Project build system Poky.
|
||||
See the <ulink url='http://www.vernier.com/products/interfaces/labq/'>Vernier LabQuest</ulink>
|
||||
for more information.
|
||||
There are a number of pre-production devices using the OpenEmbedded build system
|
||||
and the Yocto Project team
|
||||
There are a number of pre-production devices using Poky and the Yocto Project team
|
||||
announces them as soon as they are released.
|
||||
</para>
|
||||
</answer>
|
||||
@@ -126,13 +118,13 @@
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>
|
||||
What does the OpenEmbedded build system produce as output?
|
||||
What does the Yocto Project build system Poky produce as output?
|
||||
</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
Because the same set of recipes can be used to create output of various formats, the
|
||||
output of an OpenEmbedded build depends on how it was started.
|
||||
output of a Yocto Project build depends on how it was started.
|
||||
Usually, the output is a flashable image ready for the target device.
|
||||
</para>
|
||||
</answer>
|
||||
@@ -163,7 +155,7 @@
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
The OpenEmbedded build system can build packages in various formats such as
|
||||
The Yocto Project can build packages in various formats such as
|
||||
<filename>ipk</filename> for <filename>ipkg</filename>/<filename>opkg</filename>,
|
||||
Debian package (<filename>.deb</filename>), or RPM.
|
||||
The packages can then be upgraded using the package tools on the device, much like
|
||||
@@ -231,8 +223,8 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once these packages are installed, the OpenEmbedded build system will be able
|
||||
to build standard images.
|
||||
Once these packages are installed, the Yocto Project will be able to build standard
|
||||
images.
|
||||
However, there might be a problem with the QEMU emulator segfaulting.
|
||||
You can either disable the generation of binary locales by setting
|
||||
<filename><link linkend='var-ENABLE_BINARY_LOCALE_GENERATION'>ENABLE_BINARY_LOCALE_GENERATION</link>
|
||||
@@ -252,14 +244,14 @@
|
||||
<answer>
|
||||
<para>
|
||||
Nothing is wrong.
|
||||
The OpenEmbedded build system checks any configured source mirrors before downloading
|
||||
The Yocto Project checks any configured source mirrors before downloading
|
||||
from the upstream sources.
|
||||
The build system does this searching for both source archives and
|
||||
The Yocto Project does this searching for both source archives and
|
||||
pre-checked out versions of SCM managed software.
|
||||
These checks help in large installations because it can reduce load on the SCM servers
|
||||
themselves.
|
||||
The address above is one of the default mirrors configured into the
|
||||
build system.
|
||||
Yocto Project.
|
||||
Consequently, if an upstream source disappears, the team
|
||||
can place sources there so builds continue to work.
|
||||
</para>
|
||||
@@ -292,7 +284,7 @@
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
Most source fetching by the OpenEmbedded build system is done by <filename>wget</filename>
|
||||
Most source fetching by the Yocto Project is done by <filename>wget</filename>
|
||||
and you therefore need to specify the proxy settings in a
|
||||
<filename>.wgetrc</filename> file in your home directory.
|
||||
Example settings in that file would be
|
||||
@@ -358,7 +350,7 @@
|
||||
the most likely explanation is that either the hardware you're running the
|
||||
build on has some problem, or, if you are running the build under virtualisation,
|
||||
the virtualisation probably has bugs.
|
||||
The OpenEmbedded build system processes a massive amount of data causing lots of network, disk and
|
||||
The Yocto Project processes a massive amount of data causing lots of network, disk and
|
||||
CPU activity and is sensitive to even single bit failures in any of these areas.
|
||||
True random failures have always been traced back to hardware or virtualisation issues.
|
||||
</para>
|
||||
@@ -393,7 +385,7 @@
|
||||
<answer>
|
||||
<para>
|
||||
You need to create a form factor file as described in the
|
||||
"<ulink url='&YOCTO_DOCS_BSP_URL;#bsp-filelayout-misc-recipes'>Miscellaneous Recipe Files</ulink>"
|
||||
"<link linkend='bsp-filelayout-misc-recipes'>Miscellaneous Recipe Files</link>"
|
||||
section and set the <filename>HAVE_TOUCHSCREEN</filename> variable equal to one as follows:
|
||||
<literallayout class='monospaced'>
|
||||
HAVE_TOUCHSCREEN=1
|
||||
@@ -414,7 +406,7 @@
|
||||
automatically bring up network interfaces.
|
||||
Therefore, you will need to add a BSP-specific netbase that includes an interfaces
|
||||
file.
|
||||
See the "<ulink url='&YOCTO_DOCS_BSP_URL;#bsp-filelayout-misc-recipes'>Miscellaneous Recipe Files</ulink>"
|
||||
See the "<link linkend='bsp-filelayout-misc-recipes'>Miscellaneous Recipe Files</link>"
|
||||
section for information on creating these types of miscellaneous recipe files.
|
||||
</para>
|
||||
<para>
|
||||
@@ -457,7 +449,7 @@
|
||||
<answer>
|
||||
<para>
|
||||
The Yocto Project team has tried to do this before but too many of the tools
|
||||
the OpenEmbedded build system depends on such as <filename>autoconf</filename>
|
||||
the Yocto Project depends on such as <filename>autoconf</filename>
|
||||
break when they find spaces in pathnames.
|
||||
Until that situation changes, the team will not support spaces in pathnames.
|
||||
</para>
|
||||
@@ -475,29 +467,25 @@
|
||||
The toolchain configuration is very flexible and customizable.
|
||||
It is primarily controlled with the
|
||||
<filename><link linkend='var-TCMODE'>TCMODE</link></filename> variable.
|
||||
This variable controls which <filename>tcmode-*.inc</filename> file to include
|
||||
from the <filename>meta/conf/distro/include</filename> directory within the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
This variable controls which file to include
|
||||
(<filename>conf/distro/include/tcmode-*.inc</filename>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The default value of <filename>TCMODE</filename> is "default"
|
||||
(i.e. <filename>tcmode-default.inc</filename>).
|
||||
The default value of <filename>TCMODE</filename> is "default".
|
||||
However, other patterns are accepted.
|
||||
In particular, "external-*" refers to external toolchains of which there are some
|
||||
basic examples included in the OpenEmbedded Core (<filename>meta</filename>).
|
||||
You can use your own custom toolchain definition in your own layer
|
||||
In particular, "external-*" refers to external toolchains of which there are some basic examples
|
||||
included with the core.
|
||||
A user can use their own custom toolchain definition in their own layer
|
||||
(or as defined in the <filename>local.conf</filename> file) at the location
|
||||
<filename>conf/distro/include/tcmode-*.inc</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In addition to the toolchain configuration, you also need a corresponding toolchain recipe file.
|
||||
This recipe file needs to package up any pre-built objects in the toolchain such as
|
||||
<filename>libgcc</filename>, <filename>libstdcc++</filename>,
|
||||
any locales, and <filename>libc</filename>.
|
||||
An example is the <filename>external-sourcery-toolchain.bb</filename>, which is located
|
||||
in <filename>meta/recipes-core/meta/</filename> within the source directory.
|
||||
any locales and <filename>libc</filename>.
|
||||
An example is the <filename>external-csl-toolchain_2008q3-72.bb</filename>, which reuses the core
|
||||
<filename>libc</filename> packaging class to do most of the work.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
@@ -505,14 +493,14 @@
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para id='how-does-the-yocto-project-obtain-source-code-and-will-it-work-behind-my-firewall-or-proxy-server'>
|
||||
How does the OpenEmbedded build system obtain source code and will it work behind my
|
||||
How does the Yocto Project build system obtain source code and will it work behind my
|
||||
firewall or proxy server?
|
||||
</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
The way the build system obtains source code is highly configurable.
|
||||
You can setup the build system to get source code in most environments if
|
||||
The way the Yocto Project obtains source code is highly configurable.
|
||||
You can setup the Yocto Project to get source code in most environments if
|
||||
HTTP transport is available.
|
||||
</para>
|
||||
<para>
|
||||
@@ -521,8 +509,7 @@
|
||||
and then MIRRORS in that order.
|
||||
</para>
|
||||
<para>
|
||||
By default, the OpenEmbedded build system uses the Yocto Project source PREMIRRORS
|
||||
for SCM-based sources,
|
||||
By default, Poky uses the Yocto Project source PREMIRRORS for SCM-based sources,
|
||||
upstreams for normal tarballs, and then falls back to a number of other mirrors
|
||||
including the Yocto Project source mirror if those fail.
|
||||
</para>
|
||||
@@ -585,42 +572,15 @@
|
||||
any network accesses to anything other than the PREMIRROR would fail.
|
||||
</para>
|
||||
<para>
|
||||
The build system also honors the standard shell environment variables
|
||||
Poky also honors the standard shell environment variables
|
||||
<filename>http_proxy</filename>, <filename>ftp_proxy</filename>,
|
||||
<filename>https_proxy</filename>, and <filename>all_proxy</filename>
|
||||
to redirect requests through proxy servers.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
||||
<qandaentry>
|
||||
<question>
|
||||
<para>
|
||||
Can I get rid of build output so I can start over?
|
||||
</para>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
Yes - you can easily do this.
|
||||
When you use BitBake to build an image, all the build output goes into the
|
||||
directory created when you source the <filename>oe-init-build-env</filename>
|
||||
setup file.
|
||||
By default, this <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
is named <filename>build</filename> but can be named
|
||||
anything you want.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Within the build directory is the <filename>tmp</filename> directory.
|
||||
To remove all the build output yet preserve any source code or downloaded files
|
||||
from previous builds, simply remove the <filename>tmp</filename> directory.
|
||||
</para>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
|
||||
|
||||
</qandaset>
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
This manual provides reference information for the current release of the Yocto Project.
|
||||
The Yocto Project is an open-source collaboration project focused on embedded Linux
|
||||
developers.
|
||||
Amongst other things, the Yocto Project uses the OpenEmbedded build system, which
|
||||
is based on the Poky project, to construct complete Linux images.
|
||||
Amongst other things, the Yocto Project uses the Poky build tool to
|
||||
construct complete Linux images.
|
||||
You can find complete introductory and getting started information on the Yocto Project
|
||||
by reading the
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;'>
|
||||
@@ -42,44 +42,49 @@
|
||||
behind how the Yocto Project uses shared state (sstate) cache to speed build time.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-structure'>Directory Structure</link>:</emphasis>
|
||||
This chapter describes the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink> created
|
||||
either by unpacking a released Yocto Project tarball on your host development system,
|
||||
or by cloning the upstream
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#poky'>Poky</ulink> Git repository.
|
||||
</para></listitem>
|
||||
<link linkend='bsp'>Board Support Packages (BSP) - Developer's Guide</link>:</emphasis>
|
||||
This chapter describes the example filesystem layout for BSP development and
|
||||
the click-through licensing scheme.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-bitbake'>BitBake</link>:</emphasis>
|
||||
This chapter provides an overview of the BitBake tool and its role within
|
||||
<link linkend='platdev'>Platform Development With the Yocto Project</link>:</emphasis>
|
||||
This chapter describes application development, debugging, and profiling using
|
||||
the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-classes'>Classes</link>:</emphasis>
|
||||
This chapter describes the classes used in the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-images'>Images</link>:</emphasis>
|
||||
This chapter describes the standard images that the Yocto Project supports.
|
||||
<link linkend='ref-structure'>Reference: Directory Structure</link>:</emphasis>
|
||||
This appendix describes the directory structure of the Yocto Project files.
|
||||
The Yocto Project files represent the file structure or Git repository created
|
||||
as a result of setting up the Yocto Project on your host development system.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-features'>Features</link>:</emphasis>
|
||||
This chapter describes mechanisms for creating distribution, machine, and image
|
||||
features during the build process using the OpenEmbedded build system.</para></listitem>
|
||||
<link linkend='ref-bitbake'>Reference: BitBake</link>:</emphasis>
|
||||
This appendix provides an overview of the BitBake tool and its role within
|
||||
the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-variables-glos'>Variables Glossary</link>:</emphasis>
|
||||
This chapter presents most variables used by the OpenEmbedded build system, which
|
||||
using BitBake.
|
||||
<link linkend='ref-classes'>Reference: Classes</link>:</emphasis>
|
||||
This appendix describes the classes used in the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-images'>Reference: Images</link>:</emphasis>
|
||||
This appendix describes the standard images that the Yocto Project supports.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-features'>Reference: Features</link>:</emphasis>
|
||||
This appendix describes mechanisms for creating distribution, machine, and image
|
||||
features during the build process using the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-variables-glos'>Reference: Variables Glossary</link>:</emphasis>
|
||||
This appendix presents most Yocto Project variables.
|
||||
Entries describe the function of the variable and how to apply them.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='ref-varlocality'>Variable Context</link>:</emphasis>
|
||||
This chapter provides variable locality or context.</para></listitem>
|
||||
<link linkend='ref-varlocality'>Reference: Variable Context</link>:</emphasis>
|
||||
This appendix provides variable locality or context.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='faq'>FAQ</link>:</emphasis>
|
||||
This chapter provides answers for commonly asked questions in the Yocto Project
|
||||
<link linkend='faq'>Reference: FAQ</link>:</emphasis>
|
||||
This appendix provides answers for commonly asked questions in the Yocto Project
|
||||
development environment.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<link linkend='resources'>Contributing to the Yocto Project</link>:</emphasis>
|
||||
This chapter provides guidance on how you can contribute back to the Yocto
|
||||
<link linkend='resources'>Reference: Contributing to the Yocto Project</link>:</emphasis>
|
||||
This appendix provides guidance on how you can contribute back to the Yocto
|
||||
Project.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
@@ -90,7 +95,7 @@
|
||||
<title>System Requirements</title>
|
||||
<para>
|
||||
For Yocto Project system requirements, see the
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;#yp-resources'>
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;#resources'>
|
||||
What You Need and How You Get It</ulink> section in the Yocto Project Quick Start.
|
||||
</para>
|
||||
</section>
|
||||
@@ -119,11 +124,9 @@
|
||||
<section id='intro-getit-dev'>
|
||||
<title>Development Checkouts</title>
|
||||
<para>
|
||||
Development using the Yocto Project requires a local
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
You can set up the source directory by downloading a Yocto Project release tarball and unpacking it,
|
||||
or by cloning a copy of the upstream
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#poky'>Poky</ulink> Git repository.
|
||||
Development using the Yocto Project requires a local copy of the Yocto Project files.
|
||||
You can get these files by downloading a Yocto Project release tarball and unpacking it,
|
||||
or by establishing a Git repository of the files.
|
||||
For information on both these methods, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#getting-setup'>Getting Setup</ulink>"
|
||||
section in The Yocto Project Development Manual.
|
||||
|
||||
@@ -2,18 +2,18 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<book id='poky-ref-manual' lang='en'
|
||||
<book id='poky-ref-manual' lang='en'
|
||||
xmlns:xi="http://www.w3.org/2003/XInclude"
|
||||
xmlns="http://docbook.org/ns/docbook"
|
||||
>
|
||||
<bookinfo>
|
||||
|
||||
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref='figures/poky-title.png'
|
||||
format='SVG'
|
||||
<imagedata fileref='figures/poky-title.png'
|
||||
format='SVG'
|
||||
align='left' scalefit='1' width='100%'/>
|
||||
</imageobject>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
|
||||
<title></title>
|
||||
@@ -27,6 +27,19 @@
|
||||
<email>richard.purdie@linuxfoundation.org</email>
|
||||
</author>
|
||||
|
||||
<!-- <author>
|
||||
<firstname>Tomas</firstname> <surname>Frydrych</surname>
|
||||
<affiliation>
|
||||
<orgname>Intel Corporation</orgname>
|
||||
</affiliation>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<firstname>Marcin</firstname> <surname>Juszkiewicz</surname>
|
||||
</author>
|
||||
<author>
|
||||
<firstname>Dodji</firstname> <surname>Seketeli</surname>
|
||||
</author> -->
|
||||
</authorgroup>
|
||||
|
||||
<revhistory>
|
||||
@@ -56,9 +69,14 @@
|
||||
<revremark>Released with the Yocto Project 1.2 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
<revnumber>1.2.1</revnumber>
|
||||
<date>July 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.2.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.2.2</revnumber>
|
||||
<date>January 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.2.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
@@ -69,12 +87,12 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
the terms of the <ulink type="http" url="http://creativecommons.org/licenses/by-sa/2.0/uk/">Creative Commons Attribution-Share Alike 2.0 UK: England & Wales</ulink> as published by Creative Commons.
|
||||
</para>
|
||||
<note>
|
||||
Due to production processes, there could be differences between the Yocto Project
|
||||
documentation bundled in the release tarball and
|
||||
documentation bundled in the release tarball and
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;'>
|
||||
The Yocto Project Reference Manual</ulink> on
|
||||
the <ulink url='&YOCTO_HOME_URL;'>Yocto Project</ulink> website.
|
||||
@@ -90,6 +108,10 @@
|
||||
|
||||
<xi:include href="technical-details.xml"/>
|
||||
|
||||
<xi:include href="../bsp-guide/bsp.xml"/>
|
||||
|
||||
<xi:include href="development.xml"/>
|
||||
|
||||
<xi:include href="ref-structure.xml"/>
|
||||
|
||||
<xi:include href="ref-bitbake.xml"/>
|
||||
@@ -110,10 +132,10 @@
|
||||
|
||||
<!-- <index id='index'>
|
||||
<title>Index</title>
|
||||
</index>
|
||||
</index>
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='ref-bitbake'>
|
||||
<appendix id='ref-bitbake'>
|
||||
|
||||
<title>BitBake</title>
|
||||
<title>Reference: BitBake</title>
|
||||
|
||||
<para>
|
||||
BitBake is a program written in Python that interprets the metadata used by the OpenEmbedded
|
||||
build system.
|
||||
BitBake is a program written in Python that interprets the metadata that makes up the Yocto Project.
|
||||
At some point, developers wonder what actually happens when you enter:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake core-image-sato
|
||||
@@ -16,7 +15,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This chapter provides an overview of what happens behind the scenes from BitBake's perspective.
|
||||
This appendix provides an overview of what happens behind the scenes from BitBake's perspective.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
@@ -35,22 +34,20 @@
|
||||
|
||||
<para>
|
||||
The first thing BitBake does is look for the <filename>bitbake.conf</filename> file.
|
||||
This file resides in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>
|
||||
within the <filename>meta/conf/</filename> directory.
|
||||
BitBake finds it by examining its
|
||||
<link linkend='var-BBPATH'><filename>BBPATH</filename></link> environment
|
||||
The Yocto Project keeps this file in the Yocto Project file's <filename>meta/conf/</filename>
|
||||
directory.
|
||||
BitBake finds it by examining its <filename>BBPATH</filename> environment
|
||||
variable and looking for the <filename>meta/conf/</filename>
|
||||
directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>bitbake.conf</filename> file lists other configuration
|
||||
In the Yocto Project, <filename>bitbake.conf</filename> lists other configuration
|
||||
files to include from a <filename>conf/</filename>
|
||||
directory below the directories listed in <filename>BBPATH</filename>.
|
||||
In general, the most important configuration file from a user's perspective
|
||||
is <filename>local.conf</filename>, which contains a user's customized
|
||||
settings for the OpenEmbedded build environment.
|
||||
settings for the Yocto Project build environment.
|
||||
Other notable configuration files are the distribution
|
||||
configuration file (set by the
|
||||
<filename><link linkend='var-DISTRO'>DISTRO</link></filename> variable)
|
||||
@@ -186,7 +183,7 @@
|
||||
<para>
|
||||
Dependencies are defined through several variables.
|
||||
You can find information about variables BitBake uses in the
|
||||
<ulink url='&BITBAKE_DOCS_URL;'>BitBake manual</ulink>.
|
||||
<ulink url='http://bitbake.berlios.de/manual/'>BitBake manual</ulink>.
|
||||
At a basic level, it is sufficient to know that BitBake uses the
|
||||
<filename><link linkend='var-DEPENDS'>DEPENDS</link></filename> and
|
||||
<filename><link linkend='var-RDEPENDS'>RDEPENDS</link></filename> variables when
|
||||
@@ -393,7 +390,7 @@ Options:
|
||||
Fetchers are usually triggered by entries in
|
||||
<filename><link linkend='var-SRC_URI'>SRC_URI</link></filename>.
|
||||
You can find information about the options and formats of entries for specific
|
||||
fetchers in the <ulink url='&BITBAKE_DOCS_URL;'>BitBake manual</ulink>.
|
||||
fetchers in the <ulink url='http://bitbake.berlios.de/manual/'>BitBake manual</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -405,13 +402,13 @@ Options:
|
||||
This feature works using the <filename><link linkend='var-SRCREV'>SRCREV</link></filename>
|
||||
variable.
|
||||
See the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#platdev-appdev-srcrev'>Using an External SCM</ulink>" section
|
||||
in the Yocto Project Development Manual for more information.
|
||||
"<link linkend='platdev-appdev-srcrev'>Development Within Yocto Project for a Package that Uses
|
||||
an External SCM</link>" section for more information.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4 spell spelllang=en_gb
|
||||
-->
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='ref-classes'>
|
||||
<title>Classes</title>
|
||||
<appendix id='ref-classes'>
|
||||
<title>Reference: Classes</title>
|
||||
|
||||
<para>
|
||||
Class files are used to abstract common functionality and share it amongst multiple
|
||||
@@ -12,11 +12,10 @@
|
||||
file.
|
||||
Class files are identified by the extension <filename>.bbclass</filename> and are usually placed
|
||||
in a <filename>classes/</filename> directory beneath the
|
||||
<filename>meta*/</filename> directory found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
<filename>meta*/</filename> directory found in the Yocto Project file's area
|
||||
Class files can also be pointed to by BUILDDIR (e.g. <filename>build/</filename>)in the same way as
|
||||
<filename>.conf</filename> files in the <filename>conf</filename> directory.
|
||||
Class files are searched for in <link linkend='var-BBPATH'><filename>BBPATH</filename></link>
|
||||
Class files are searched for in <filename>BBPATH</filename>
|
||||
using the same method by which <filename>.conf</filename> files are searched.
|
||||
</para>
|
||||
|
||||
@@ -112,7 +111,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Currently, the OpenEmbedded build system supports only one binary per package.
|
||||
Currently, the Yocto Project supports only one binary per package.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -122,7 +121,7 @@
|
||||
<para>
|
||||
This class uses <filename>update-rc.d</filename> to safely install an
|
||||
initialization script on behalf of the package.
|
||||
The OpenEmbedded build system takes care of details such as making sure the script is stopped before
|
||||
The Yocto Project takes care of details such as making sure the script is stopped before
|
||||
a package is removed and started when the package is installed.
|
||||
Three variables control this class:
|
||||
<filename><link linkend='var-INITSCRIPT_PACKAGES'>INITSCRIPT_PACKAGES</link></filename>,
|
||||
@@ -255,10 +254,10 @@
|
||||
|
||||
<para>
|
||||
This class adds the <filename>devshell</filename> task.
|
||||
Distribution policy dictates whether to include this class.
|
||||
Distribution policy dictates whether to include this class as the Yocto Project does.
|
||||
See the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#platdev-appdev-devshell'>Using a Development Shell</ulink>" section
|
||||
in the Yocto Project Development Manual for more information about using <filename>devshell</filename>.
|
||||
"<link linkend='platdev-appdev-devshell'>Development Within a Development Shell</link>" section
|
||||
for more information about using devshell.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -278,9 +277,8 @@
|
||||
<para>
|
||||
You can control the list of resulting package formats by using the
|
||||
<filename><link linkend='var-PACKAGE_CLASSES'>PACKAGE_CLASSES</link></filename>
|
||||
variable defined in the <filename>local.conf</filename> configuration file,
|
||||
which is located in the <filename>conf</filename> folder of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
variable defined in the <filename>local.conf</filename> configuration file
|
||||
found in the Yocto Project file's <filename>conf</filename> directory.
|
||||
When defining the variable, you can specify one or more package types.
|
||||
Since images are generated from packages, a packaging class is
|
||||
needed to enable image generation.
|
||||
@@ -382,7 +380,7 @@
|
||||
The class also performs basic user configuration checks from
|
||||
the <filename>local.conf</filename> configuration file to
|
||||
prevent common mistakes that cause build failures.
|
||||
Distribution policy usually determines whether to include this class.
|
||||
Distribution policy usually whether to include this class as the Yocto Project does.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -391,10 +389,10 @@
|
||||
|
||||
<para>
|
||||
This class adds a step to the package generation process that sanity checks the
|
||||
packages generated by the OpenEmbedded build system.
|
||||
packages generated by the Yocto Project.
|
||||
A range of checks are performed that check the build's output
|
||||
for common problems that show up during runtime.
|
||||
Distribution policy usually dictates whether to include this class.
|
||||
Distribution policy usually dictates whether to include this class as the Yocto Project does.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -516,8 +514,7 @@
|
||||
you can use this class to specify those packages and associate the users and groups
|
||||
with those packages.
|
||||
The <filename>meta-skeleton/recipes-skeleton/useradd/useradd-example.bb</filename>
|
||||
recipe in the <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>
|
||||
provides a simple exmample that shows how to add three
|
||||
recipe in the Yocto Project Files provides a simple exmample that shows how to add three
|
||||
users and groups to two packages.
|
||||
See the <filename>useradd-example.bb</filename> for more information on how to
|
||||
use this class.
|
||||
@@ -529,7 +526,7 @@
|
||||
|
||||
<para>
|
||||
You can use this class to build software from source code that is external to the
|
||||
OpenEmbedded build system.
|
||||
Yocto Project build system.
|
||||
In other words, your source code resides in an external tree outside of the Yocto Project.
|
||||
Building software from an external source tree means that the normal fetch, unpack, and
|
||||
patch process is not used.
|
||||
@@ -544,7 +541,7 @@
|
||||
<para>
|
||||
This class expects the source code to support recipe builds that use the
|
||||
<link linkend='var-B'><filename>B</filename></link> variable to point to the directory in
|
||||
which the OpenEmbedded build system places the generated objects built from the recipes.
|
||||
which the Yocto Project build system places the generated objects built from the recipes.
|
||||
By default, the <filename>B</filename> directory is set to the following, which is separate from the
|
||||
source directory (<filename>S</filename>):
|
||||
<literallayout class='monospaced'>
|
||||
@@ -573,7 +570,7 @@
|
||||
When you do, the <link linkend='var-B'><filename>B</filename></link> variable must support the
|
||||
recipe's ability to build variants in different working directories.
|
||||
Most autotools-based recipes support separating these directories.
|
||||
The OpenEmbedded build system defaults to using separate directories for <filename>gcc</filename>
|
||||
The Yocto Project defaults to using separate directories for <filename>gcc</filename>
|
||||
and some kernel recipes.
|
||||
Alternatively, you can make sure that separate recipes exist that each
|
||||
use the <filename>BBCLASSEXTEND</filename> variable to build each variant.
|
||||
@@ -591,10 +588,10 @@
|
||||
<title>Other Classes</title>
|
||||
|
||||
<para>
|
||||
Thus far, this chapter has discussed only the most useful and important
|
||||
Thus far, this appendix has discussed only the most useful and important
|
||||
classes.
|
||||
However, other classes exist within the <filename>meta/classes</filename> directory
|
||||
in the <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
in the Yocto Project file's directory structure.
|
||||
You can examine the <filename>.bbclass</filename> files directly for more
|
||||
information.
|
||||
</para>
|
||||
@@ -669,7 +666,7 @@
|
||||
-->
|
||||
|
||||
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='ref-features'>
|
||||
<appendix id='ref-features'>
|
||||
<title>Reference: Features</title>
|
||||
|
||||
<para>
|
||||
@@ -115,7 +115,7 @@
|
||||
<title>Reference: Images</title>
|
||||
|
||||
<para>
|
||||
The contents of images generated by the OpenEmbedded build system can be controlled by the
|
||||
The contents of images generated by the Yocto Project can be controlled by the
|
||||
<filename><link linkend='var-IMAGE_FEATURES'>IMAGE_FEATURES</link></filename>
|
||||
and <filename><link linkend='var-EXTRA_IMAGE_FEATURES'>EXTRA_IMAGE_FEATURES</link></filename>
|
||||
variables that you typically configure in your image recipes.
|
||||
@@ -157,7 +157,7 @@
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
</appendix>
|
||||
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4 spell spelllang=en_gb
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='ref-images'>
|
||||
<title>Images</title>
|
||||
<appendix id='ref-images'>
|
||||
<title>Reference: Images</title>
|
||||
|
||||
<para>
|
||||
The OpenEmbedded build process supports several types of images to satisfy different needs.
|
||||
The Yocto Project build process supports several types of images to satisfy different needs.
|
||||
When you issue the <filename>bitbake</filename> command you provide a “top-level” recipe
|
||||
that essentially begins the build for the type of image you want.
|
||||
</para>
|
||||
@@ -32,8 +32,8 @@
|
||||
These recipes reside in the <filename>meta/recipes-core/images</filename>,
|
||||
<filename>meta/recipes-extended/images</filename>,
|
||||
<filename>meta/recipes-graphics/images</filename>, and
|
||||
<filename>meta/recipes-sato/images</filename> directories
|
||||
within the <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
<filename>meta/recipes-sato/images</filename> directories of your local Yocto Project
|
||||
file structure (Git repository or extracted release tarball).
|
||||
Although the recipe names are somewhat explanatory, here is a list that describes them:
|
||||
</para>
|
||||
|
||||
@@ -46,10 +46,7 @@
|
||||
<listitem><para><emphasis><filename>core-image-minimal</filename>:</emphasis>
|
||||
A small image just capable of allowing a device to boot.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-minimal-dev</filename>:</emphasis>
|
||||
A <filename>core-image-minimal</filename> image suitable for development work
|
||||
using the host.
|
||||
The image includes headers and libraries you can use in a host development
|
||||
environment.
|
||||
A <filename>core-image-minimal</filename> image suitable for development work.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-minimal-initramfs</filename>:</emphasis>
|
||||
A <filename>core-image-minimal</filename> image that has the Minimal RAM-based
|
||||
@@ -68,15 +65,13 @@
|
||||
A <filename>core-image-basic</filename> image suitable for implementations
|
||||
that conform to Linux Standard Base (LSB).</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-lsb-dev</filename>:</emphasis>
|
||||
A <filename>core-image-lsb</filename> image that is suitable for development work
|
||||
using the host.
|
||||
The image includes headers and libraries you can use in a host development
|
||||
environment.
|
||||
A <filename>core-image-lsb</filename> image that is suitable for development work.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-lsb-sdk</filename>:</emphasis>
|
||||
A <filename>core-image-lsb</filename> that includes everything in meta-toolchain
|
||||
but also includes development headers and libraries to form a complete standalone SDK.
|
||||
This image is suitable for development using the target.</para></listitem>
|
||||
but also includes development headers and libraries to form a complete standalone SDK.
|
||||
See the "<link linkend='platdev-appdev-external-sdk'>External Development Using the Meta-Toolchain</link>"
|
||||
section for more information.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-clutter</filename>:</emphasis>
|
||||
An image with support for the Open GL-based toolkit Clutter, which enables development of
|
||||
rich and animated graphical user interfaces.</para></listitem>
|
||||
@@ -86,15 +81,16 @@
|
||||
The image supports X11 with a Sato theme and Pimlico applications and also
|
||||
contains terminal, editor, and file manager.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-sato-dev</filename>:</emphasis>
|
||||
A <filename>core-image-sato</filename> image suitable for development
|
||||
using the host.
|
||||
The image includes libraries needed to build applications on the device itself,
|
||||
testing and profiling tools, and debug symbols.
|
||||
A <filename>core-image-sato</filename> image suitable for development
|
||||
that also includes a native toolchain and libraries needed to build applications on
|
||||
the device itself.
|
||||
The image also includes testing and profiling tools as well as debug symbols.
|
||||
This image was formerly <filename>core-image-sdk</filename>.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-sato-sdk</filename>:</emphasis>
|
||||
A <filename>core-image-sato</filename> image that includes everything in meta-toolchain.
|
||||
The image also includes development headers and libraries to form a complete standalone SDK
|
||||
and is suitable for development using the target.</para></listitem>
|
||||
The image also includes development headers and libraries to form a complete standalone SDK.
|
||||
See the "<link linkend='platdev-appdev-external-sdk'>External Development Using the Meta-Toolchain</link>"
|
||||
section for more information.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-rt</filename>:</emphasis>
|
||||
A <filename>core-image-minimal</filename> image plus a real-time test suite and
|
||||
tools appropriate for real-time use.</para></listitem>
|
||||
@@ -102,17 +98,20 @@
|
||||
A <filename>core-image-rt</filename> image that includes everything in
|
||||
<filename>meta-toolchain</filename>.
|
||||
The image also includes development headers and libraries to form a complete
|
||||
stand-alone SDK and is suitable for development using the target.</para></listitem>
|
||||
stand-alone SDK.
|
||||
See the "<link linkend='platdev-appdev-external-sdk'>External Development Using the Meta-Toolchain</link>"
|
||||
section for more information.</para></listitem>
|
||||
<listitem><para><emphasis><filename>core-image-gtk-directfb</filename>:</emphasis>
|
||||
An image that uses <filename>gtk+</filename> over <filename>directfb</filename>
|
||||
instead of X11.
|
||||
In order to build, this image requires specific distro configuration that enables
|
||||
<filename>gtk</filename> over <filename>directfb</filename>.</para></listitem>
|
||||
<listitem><para><emphasis><filename>build-appliance-image</filename>:</emphasis>
|
||||
An image you can boot and run using either the
|
||||
<listitem><para><emphasis><filename>self-hosted-image</filename>:</emphasis>
|
||||
An image you can run using the Yocto Project Build Appliance.
|
||||
The image is suitable to load and boot from either
|
||||
<ulink url='http://www.vmware.com/products/player/overview.html'>VMware Player</ulink>
|
||||
or <ulink url='http://www.vmware.com/products/workstation/overview.html'>VMware Workstation</ulink>.
|
||||
For more information on this image, see the
|
||||
or <ulink url='http://www.vmware.com/products/workstation/overview.html'>VMWare Workstation</ulink>.
|
||||
For more information on the Build Appliance, see the
|
||||
<ulink url='&YOCTO_HOME_URL;/documentation/build-appliance'>Build Appliance</ulink> page on
|
||||
the Yocto Project website.</para></listitem>
|
||||
</itemizedlist>
|
||||
@@ -127,7 +126,7 @@
|
||||
"live" to <filename>IMAGE_FSTYPES</filename> within the <filename>local.conf</filename>
|
||||
file or wherever appropriate and then build the desired image as normal.
|
||||
</tip>
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<chapter id='ref-structure'>
|
||||
<appendix id='ref-structure'>
|
||||
|
||||
<title>Source Directory Structure</title>
|
||||
<title>Reference: Directory Structure</title>
|
||||
|
||||
<para>
|
||||
The <ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink> consists of several components.
|
||||
The Yocto Project consists of several components.
|
||||
Understanding them and knowing where they are located is key to using the Yocto Project well.
|
||||
This chapter describes the source directory and gives information about the various
|
||||
This appendix describes the Yocto Project file's directory structure and gives information about the various
|
||||
files and directories.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For information on how to establish a local source directory on your development system, see the
|
||||
For information on how to establish the Yocto Project files on your local development system, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#getting-setup'>Getting Set Up</ulink>"
|
||||
section in the Yocto Project Development Manual.
|
||||
</para>
|
||||
@@ -26,28 +26,21 @@
|
||||
<title><filename>bitbake/</filename></title>
|
||||
|
||||
<para>
|
||||
The <ulink url='source-directory'>source directory</ulink>
|
||||
includes a copy of BitBake for ease of use.
|
||||
The Yocto Project includes a copy of BitBake for ease of use.
|
||||
The copy usually matches the current stable BitBake release from the BitBake project.
|
||||
BitBake, a metadata interpreter, reads the Yocto Project metadata and runs the tasks
|
||||
defined by that data.
|
||||
Failures are usually from the metadata and not from BitBake itself.
|
||||
Failures are usually from the metadata and not
|
||||
from BitBake itself.
|
||||
Consequently, most users do not need to worry about BitBake.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you run the <filename>bitbake</filename> command, the wrapper script in
|
||||
<filename>scripts/</filename> is executed to run the main BitBake executable,
|
||||
which resides in the <filename>bitbake/bin/</filename> directory.
|
||||
Sourcing the <link linkend="structure-core-script">oe-init-build-env</link>
|
||||
script places the <filename>scripts</filename> and <filename>bitbake/bin</filename>
|
||||
directories (in that order) into the shell's <filename>PATH</filename> environment
|
||||
variable.
|
||||
The <filename>bitbake/bin/</filename> directory is placed
|
||||
into the shell's <filename>PATH</filename> environment variable by the
|
||||
<link linkend="structure-core-script">oe-init-build-env</link> script.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For more information on BitBake, see the BitBake on-line manual at
|
||||
<ulink url="http://docs.openembedded.org/bitbake/html/"/>.
|
||||
<ulink url="http://bitbake.berlios.de/manual/"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -56,20 +49,18 @@
|
||||
|
||||
<para>
|
||||
This directory contains user configuration files and the output
|
||||
generated by the OpenEmbedded build system in its standard configuration where
|
||||
the source tree is combined with the output.
|
||||
The <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
is created initially when you <filename>source</filename>
|
||||
the OpenEmbedded build environment setup script <filename>oe-init-build-env</filename>.
|
||||
generated by the Yocto Project in its standard configuration where the source tree is
|
||||
combined with the output.
|
||||
The build directory is created initially when you <filename>source</filename>
|
||||
the Yocto Project environment setup script <filename>oe-init-build-env</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is also possible to place output and configuration
|
||||
files in a directory separate from the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>
|
||||
files in a directory separate from the Yocto Project files
|
||||
by providing a directory name when you <filename>source</filename>
|
||||
the setup script.
|
||||
For information on separating output from your local source directory files, see <link
|
||||
For information on separating output from the Yocto Project files, see <link
|
||||
linkend='structure-core-script'>oe-init-build-env</link>.
|
||||
</para>
|
||||
</section>
|
||||
@@ -91,7 +82,7 @@
|
||||
<title><filename>meta/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory contains the OpenEmbedded Core metadata.
|
||||
This directory contains the Yocto Project core metadata.
|
||||
The directory holds machine definitions, the Yocto Project distribution,
|
||||
and the packages that make up a given system.
|
||||
</para>
|
||||
@@ -102,7 +93,7 @@
|
||||
|
||||
<para>
|
||||
This directory contains recipes for applications and demos that are not part of the
|
||||
OpenEmbedded core.
|
||||
Yocto Project core.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -143,7 +134,7 @@
|
||||
<title><filename>oe-init-build-env</filename></title>
|
||||
|
||||
<para>
|
||||
This script sets up the OpenEmbedded build environment.
|
||||
This script sets up the Yocto Project build environment.
|
||||
Running this script with the <filename>source</filename> command in
|
||||
a shell makes changes to <filename>PATH</filename> and sets other core BitBake variables based on the
|
||||
current working directory.
|
||||
@@ -156,11 +147,9 @@
|
||||
By default, running this script without a build directory argument creates the
|
||||
<filename>build</filename> directory.
|
||||
If you provide a build directory argument when you <filename>source</filename>
|
||||
the script, you direct OpenEmbedded build system to create a
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink> of your choice.
|
||||
the script, you direct the Yocto Project to create a build directory of your choice.
|
||||
For example, the following command creates a build directory named
|
||||
<filename>mybuilds</filename> that is outside of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>:
|
||||
<filename>mybuilds</filename> that is outside of the Yocto Project files:
|
||||
<literallayout class='monospaced'>
|
||||
$ source oe-init-build-env ~/mybuilds
|
||||
</literallayout>
|
||||
@@ -192,12 +181,12 @@
|
||||
<title><filename>build/conf/local.conf</filename></title>
|
||||
|
||||
<para>
|
||||
This file contains all the local user configuration for your build environment.
|
||||
This file contains all the local user configuration of the Yocto Project.
|
||||
If there is no <filename>local.conf</filename> present, it is created from
|
||||
<filename>local.conf.sample</filename>.
|
||||
The <filename>local.conf</filename> file contains documentation on the various configuration options.
|
||||
Any variable set here overrides any variable set elsewhere within the environment unless
|
||||
that variable is hard-coded within a file (e.g. by using '=' instead of '?=').
|
||||
Any variable set here overrides any variable set elsewhere within the Yocto Project unless
|
||||
that variable is hard-coded within the Yocto Project (e.g. by using '=' instead of '?=').
|
||||
Some variables are hard-coded for various reasons but these variables are
|
||||
relatively rare.
|
||||
</para>
|
||||
@@ -255,11 +244,10 @@
|
||||
<title><filename>build/tmp/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory receives all the OpenEmbedded build system's output.
|
||||
This directory receives all the Yocto Project output.
|
||||
BitBake creates this directory if it does not exist.
|
||||
As a last resort, to clean up a build and start it from scratch (other than the downloads),
|
||||
you can remove everything in the <filename>tmp</filename> directory or get rid of the
|
||||
directory completely.
|
||||
As a last resort, to clean the Yocto Project and start a build from scratch (other than downloads),
|
||||
you can remove everything in this directory or get rid of the directory completely.
|
||||
If you do, you should also completely remove the <filename>build/sstate-cache</filename>
|
||||
directory as well.
|
||||
</para>
|
||||
@@ -287,7 +275,7 @@
|
||||
<title><filename>build/tmp/deploy/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory contains any 'end result' output from the OpenEmbedded build process.
|
||||
This directory contains any 'end result' output from the Yocto Project build process.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -295,8 +283,7 @@
|
||||
<title><filename>build/tmp/deploy/deb/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory receives any <filename>.deb</filename> packages produced by
|
||||
the build process.
|
||||
This directory receives any <filename>.deb</filename> packages produced by the Yocto Project.
|
||||
The packages are sorted into feeds for different architecture types.
|
||||
</para>
|
||||
</section>
|
||||
@@ -305,23 +292,11 @@
|
||||
<title><filename>build/tmp/deploy/rpm/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory receives any <filename>.rpm</filename> packages produced by
|
||||
the build process.
|
||||
This directory receives any <filename>.rpm</filename> packages produced by the Yocto Project.
|
||||
The packages are sorted into feeds for different architecture types.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='structure-build-tmp-deploy-licenses'>
|
||||
<title><filename>build/tmp/deploy/licenses/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory receives package licensing information.
|
||||
For example, the directory contains sub-directories for <filename>bash</filename>,
|
||||
<filename>busybox</filename>, and <filename>eglibc</filename> (among others) that in turn
|
||||
contain appropriate <filename>COPYING</filename> license files with other licensing information.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='structure-build-tmp-deploy-images'>
|
||||
<title><filename>build/tmp/deploy/images/</filename></title>
|
||||
|
||||
@@ -344,9 +319,7 @@
|
||||
<section id='structure-build-tmp-deploy-ipk'>
|
||||
<title><filename>build/tmp/deploy/ipk/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory receives <filename>.ipk</filename> packages produced by
|
||||
the build process.</para>
|
||||
<para>This directory receives <filename>.ipk</filename> packages produced by the Yocto Project.</para>
|
||||
</section>
|
||||
|
||||
<section id='structure-build-tmp-sysroots'>
|
||||
@@ -381,7 +354,6 @@
|
||||
package's <filename><link linkend='var-WORKDIR'>WORKDIR</link></filename>.
|
||||
Examples of logs are the output from the <filename>check_pkg</filename> or
|
||||
<filename>distro_check</filename> tasks.
|
||||
Running a build does not necessarily mean this directory is created.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -408,8 +380,7 @@
|
||||
|
||||
<para>
|
||||
It is worth considering the structure of a typical work directory.
|
||||
As an example, consider the <filename>linux-yocto-kernel-3.0</filename>
|
||||
on the machine <filename>qemux86</filename>
|
||||
As an example, consider the linux-yocto kernel 3.0 on the machine <filename>qemux86</filename>
|
||||
built within the Yocto Project.
|
||||
For this package, a work directory of
|
||||
<filename>tmp/work/qemux86-poky-linux/linux-yocto-3.0+git1+<.....></filename>,
|
||||
@@ -484,7 +455,7 @@
|
||||
<para>
|
||||
This directory contains all the machine configuration files.
|
||||
If you set <filename>MACHINE="qemux86"</filename>,
|
||||
the OpenEmbedded build system looks for a <filename>qemux86.conf</filename> file in this
|
||||
Yocto Project looks for a <filename>qemux86.conf</filename> file in this
|
||||
directory.
|
||||
The <filename>include</filename> directory contains various data common to multiple machines.
|
||||
If you want to add support for a new machine to the Yocto Project, look in this directory.
|
||||
@@ -496,11 +467,12 @@
|
||||
|
||||
<para>
|
||||
Any distribution-specific configuration is controlled from this directory.
|
||||
For the Yocto Project, the <filename>defaultsetup.conf</filename> is the main file here.
|
||||
The Yocto Project only contains the Yocto Project distribution so
|
||||
<filename>defaultsetup.conf</filename> is the main file here.
|
||||
This directory includes the versions and the
|
||||
<filename>SRCDATE</filename> definitions for applications that are configured here.
|
||||
An example of an alternative configuration might be <filename>poky-bleeding.conf</filename>.
|
||||
Although this file mainly inherits its configuration from Poky.
|
||||
An example of an alternative configuration is <filename>poky-bleeding.conf</filename>
|
||||
although this file mainly inherits its configuration from the Yocto Project itself.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -591,15 +563,6 @@
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='structure-meta-recipes-rt'>
|
||||
<title><filename>meta/recipes-rt/</filename></title>
|
||||
|
||||
<para>
|
||||
This directory contains package and image recipes for using and testing
|
||||
the <filename>PREEMPT_RT</filename> kernel.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='structure-meta-recipes-sato'>
|
||||
<title><filename>meta/recipes-sato/</filename></title>
|
||||
|
||||
@@ -630,7 +593,7 @@
|
||||
</section>
|
||||
|
||||
<section id='structure-meta-recipes-txt'>
|
||||
<title><filename>meta/recipes.txt</filename></title>
|
||||
<title><filename>meta/recipes.txt/</filename></title>
|
||||
|
||||
<para>
|
||||
This file is a description of the contents of <filename>recipes-*</filename>.
|
||||
@@ -638,7 +601,7 @@
|
||||
</section>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] >
|
||||
|
||||
<!-- Dummy chapter -->
|
||||
<chapter id='ref-variables-glos'>
|
||||
<appendix id='ref-variables-glos'>
|
||||
|
||||
<title>Variables Glossary</title>
|
||||
<title>Reference: Variables Glossary</title>
|
||||
|
||||
<para>
|
||||
This chapter lists common variables used in the OpenEmbedded build system and gives an overview
|
||||
This section lists common variables used in the Yocto Project and gives an overview
|
||||
of their function and contents.
|
||||
</para>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<link linkend='var-HOMEPAGE'>H</link>
|
||||
<link linkend='var-IMAGE_FEATURES'>I</link>
|
||||
<!-- <link linkend='var-glossary-j'>J</link> -->
|
||||
<link linkend='var-KBRANCH'>K</link>
|
||||
<link linkend='var-KERNEL_FEATURES'>K</link>
|
||||
<link linkend='var-LAYERDIR'>L</link>
|
||||
<link linkend='var-MACHINE'>M</link>
|
||||
<!-- <link linkend='var-glossary-n'>N</link> -->
|
||||
@@ -89,7 +89,7 @@
|
||||
<glossentry id='var-B'><glossterm>B</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
The directory in which the OpenEmbedded build system places
|
||||
The directory in which the Yocto Project build system places
|
||||
generated objects during a recipe's build process.
|
||||
By default, this directory is the same as the <link linkend='var-S'><filename>S</filename></link>
|
||||
directory:
|
||||
@@ -99,7 +99,7 @@
|
||||
You can separate the source directory (<filename>S</filename>) and the directory pointed to
|
||||
by the <filename>B</filename> variable.
|
||||
Most autotools-based recipes support separating these directories.
|
||||
The build system defaults to using separate directories for <filename>gcc</filename>
|
||||
The Yocto Project defaults to using separate directories for <filename>gcc</filename>
|
||||
and some kernel recipes.
|
||||
</para>
|
||||
</glossdef>
|
||||
@@ -160,7 +160,7 @@
|
||||
</literallayout></para>
|
||||
<para>Use the <filename>BBMASK</filename> variable from within the
|
||||
<filename>conf/local.conf</filename> file found
|
||||
in the <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.</para>
|
||||
in the Yocto Project build directory.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
@@ -243,9 +243,9 @@
|
||||
|
||||
<glossentry id='var-BBLAYERS'><glossterm>BBLAYERS</glossterm>
|
||||
<glossdef>
|
||||
<para>Lists the layers to enable during the build.
|
||||
<para>Lists the layers to enable during the Yocto Project build.
|
||||
This variable is defined in the <filename>bblayers.conf</filename> configuration
|
||||
file in the <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
file in the Yocto Project build directory.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
BBLAYERS = " \
|
||||
@@ -335,8 +335,8 @@
|
||||
<filename>/etc</filename> or <filename>${bindir}</filename> rather
|
||||
than <filename>/usr/bin</filename>.
|
||||
You can find a list of these variables at the top of the
|
||||
<filename>/meta/conf/bitbake.conf</filename> file in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
<filename>/meta/conf/bitbake.conf</filename> file in the Yocto Project
|
||||
files directory.
|
||||
</note>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
@@ -358,7 +358,7 @@
|
||||
Specifies the list of packages to be added to the image.
|
||||
This variable should only be set in the <filename>local.conf</filename>
|
||||
configuration file found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>Yocto Project Build Directory</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -479,7 +479,7 @@
|
||||
This directory is self-maintaining and you should not have
|
||||
to touch it.
|
||||
By default, the directory is <filename>downloads</filename> in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
Yocto Project build directory.
|
||||
<literallayout class='monospaced'>
|
||||
#DL_DIR ?= "${TOPDIR}/downloads"
|
||||
</literallayout>
|
||||
@@ -507,7 +507,7 @@
|
||||
For additional information on how the build process gets source files
|
||||
when working behind a firewall or proxy server, see the
|
||||
"<link linkend='how-does-the-yocto-project-obtain-source-code-and-will-it-work-behind-my-firewall-or-proxy-server'>FAQ</link>"
|
||||
chapter.
|
||||
appendix.
|
||||
</para>
|
||||
</glossdef>
|
||||
|
||||
@@ -635,8 +635,8 @@
|
||||
<filename>/etc</filename> or <filename>${bindir}</filename> rather
|
||||
than <filename>/usr/bin</filename>.
|
||||
You can find a list of these variables at the top of the
|
||||
<filename>/meta/conf/bitbake.conf</filename> file in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
<filename>/meta/conf/bitbake.conf</filename> file in the Yocto Project
|
||||
files directory.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
@@ -655,7 +655,7 @@
|
||||
<glossentry id='var-FILESEXTRAPATHS'><glossterm>FILESEXTRAPATHS</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
Extends the search path the OpenEmbedded build system uses when
|
||||
Extends the search path the Yocto Project build system uses when
|
||||
looking for files and patches as it processes recipes.
|
||||
The directories BitBake uses when it processes recipes is defined by the
|
||||
<link linkend='var-FILESPATH'><filename>FILESPATH</filename></link> variable.
|
||||
@@ -669,7 +669,7 @@
|
||||
<literallayout class='monospaced'>
|
||||
FILESEXTRAPATHS_prepend := "path_1:path_2:path_3:"
|
||||
</literallayout>
|
||||
Typically, you want your directories search first.
|
||||
Typically, you want your directories searched first.
|
||||
To make sure that happens, use <filename>_prepend</filename> and
|
||||
the immediate expansion (<filename>:=</filename>) operator as shown in the
|
||||
previous example.
|
||||
@@ -691,7 +691,7 @@
|
||||
<glossentry id='var-FILESPATH'><glossterm>FILESPATH</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
The default set of directories the OpenEmbedded build system uses
|
||||
The default set of directories the Yocto Project build system uses
|
||||
when searching for patches and files.
|
||||
During the build process, BitBake searches each directory in
|
||||
<filename>FILESPATH</filename> in the specified order when looking for
|
||||
@@ -702,7 +702,7 @@
|
||||
The default value for the <filename>FILESPATH</filename> variable is defined
|
||||
in the <filename>base.bbclass</filename> class found in
|
||||
<filename>meta/classes</filename> in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>:
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>Yocto Project Files</ulink>:
|
||||
<literallayout class='monospaced'>
|
||||
FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", \
|
||||
"${FILE_DIRNAME}/${P}", "${FILE_DIRNAME}/${PN}", \
|
||||
@@ -727,17 +727,16 @@ FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", \
|
||||
possible.
|
||||
</para>
|
||||
<para>
|
||||
By default, the OpenEmbedded build system uses the <filename>fs-perms.txt</filename>, which
|
||||
is located in the <filename>meta/files</filename> folder in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>.
|
||||
By default, the Yocto Project uses the <filename>fs-perms.txt</filename>, which
|
||||
is located in the <filename>meta/files</filename> directory of the Yocto Project
|
||||
files directory.
|
||||
If you create your own file permissions setting table, you should place it in your
|
||||
layer or the distros layer.
|
||||
</para>
|
||||
<para>
|
||||
You define the <filename>FILESYSTEM_PERMS_TABLES</filename> variable in the
|
||||
<filename>conf/local.conf</filename> file, which is found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>, to
|
||||
point to your custom <filename>fs-perms.txt</filename>.
|
||||
<filename>conf/local.conf</filename> file, which is found in the Yocto Project's
|
||||
build directory, to point to your custom <filename>fs-perms.txt</filename>.
|
||||
You can specify more than a single file permissions setting table.
|
||||
The paths you specify to these files must be defined within the
|
||||
<filename>BBPATH</filename> variable.
|
||||
@@ -785,8 +784,8 @@ FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", \
|
||||
Typically, you configure this variable in image recipes.
|
||||
Note that you can add extra features to the image by using the
|
||||
<filename><link linkend='var-EXTRA_IMAGE_FEATURES'>EXTRA_IMAGE_FEATURES</link></filename> variable.
|
||||
See the "<link linkend="ref-features-image">Images</link>" chapter for the
|
||||
list of features present in images built by the OpenEmbedded build system.</para>
|
||||
See the "<link linkend="ref-features-image">Reference: Images</link>" section for the
|
||||
list of features present in images built by the Yocto Project.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
@@ -909,7 +908,7 @@ FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", \
|
||||
<glossdef>
|
||||
<para>
|
||||
Defines the size in Kbytes for the generated image.
|
||||
The OpenEmbedded build system determines the final size for the generated
|
||||
The Yocto Project build system determines the final size for the generated
|
||||
image using an algorithm that takes into account the initial disk space used
|
||||
for the generated image, a requested size for the image, and requested
|
||||
additional free disk space to be added to the image.
|
||||
@@ -949,20 +948,19 @@ FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", \
|
||||
<glossdef>
|
||||
<para>Defines the Package revision.
|
||||
You manually combine values for <filename>INC_PR</filename> into the
|
||||
<link linkend='var-PR'><filename>PR</filename></link> field of the parent recipe.
|
||||
<filename>PR</filename> field of the parent recipe.
|
||||
When you change this variable, you change the <filename>PR</filename>
|
||||
value for every person that includes the file.</para>
|
||||
<para>
|
||||
The following example shows how to use the <filename>INC_PR</filename> variable
|
||||
given a common <filename>.inc</filename> file that defines the variable.
|
||||
Once defined, you can use the variable to set the
|
||||
<filename>PR</filename> value:
|
||||
Once defined, you can use the variable to set the <filename>PR</filename> value:
|
||||
</para>
|
||||
<literallayout class='monospaced'>
|
||||
recipes-graphics/xorg-font/encodings_1.0.4.bb:PR = "${INC_PR}.1"
|
||||
recipes-graphics/xorg-font/font-util_1.3.0.bb:PR = "${INC_PR}.0"
|
||||
recipes-graphics/xorg-font/font-alias_1.0.3.bb:PR = "${INC_PR}.3"
|
||||
recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
recipes-graphics/xorg-font/font-util_1.1.1.bb:PR - "$(INC_PR).1"
|
||||
recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR - "r1"
|
||||
recipes-graphics/xorg-font/encondings_1.0.3.bb:PR - "$(INC_PR).1"
|
||||
recipes-graphics/xorg-font/fiont-alias_1.0.2.bb:PR - "$(INC_PR).0"
|
||||
</literallayout>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
@@ -1035,65 +1033,10 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
|
||||
<glossdiv id='var-glossary-k'><title>K</title>
|
||||
|
||||
<glossentry id='var-KBRANCH'><glossterm>KBRANCH</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
A regular expression used by the build process to explicitly identify the kernel
|
||||
branch that is validated, patched and configured during a build.
|
||||
The <filename>KBRANCH</filename> variable is optional.
|
||||
You can use it to trigger checks to ensure the exact kernel branch you want is
|
||||
being used by the build process.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Values for this variable are set in the kernel's recipe file and the kernel's
|
||||
append file.
|
||||
For example, if you are using the Yocto Project kernel that is based on the
|
||||
Linux 3.2 kernel, the kernel recipe file is the
|
||||
<filename>meta/recipes-kernel/linux/linux-yocto_3.2.bb</filename> file.
|
||||
Following is the default value for <filename>KBRANCH</filename> and the five overrides
|
||||
for the architectures the Yocto Project supports:
|
||||
<literallayout class='monospaced'>
|
||||
KBRANCH = "standard/default/base"
|
||||
KBRANCH_qemux86 = "standard/default/common-pc/base"
|
||||
KBRANCH_qemux86-64 = "standard/default/common-pc-64/base"
|
||||
KBRANCH_qemuppc = "standard/default/qemu-ppc32"
|
||||
KBRANCH_qemumips = "standard/default/mti-malta32-be"
|
||||
KBRANCH_qemuarm = "standard/default/arm-versatile-926ejs"
|
||||
</literallayout>
|
||||
Each of the above branches exist in the <filename>linux-yocto-3.2</filename> kernel Git
|
||||
repository <ulink url='&YOCTO_GIT_URL;/cgit.cgi/linux-yocto-3.2/refs/heads'></ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This variable is also used from the kernel's append file to identify the kernel
|
||||
branch specific to a particular machine or target hardware.
|
||||
The kernel's append file is located in the BSP layer for a given machine.
|
||||
For example, the kernel append file for the Crown Bay BSP is in the
|
||||
<filename>meta-intel</filename> Git repository and is named
|
||||
<filename>meta-crownbay/recipes-kernel/linux/linux-yocto_3.2.bbappend</filename>.
|
||||
Here are the related statements from the append file:
|
||||
<literallayout class='monospaced'>
|
||||
COMPATIBLE_MACHINE_crownbay = "crownbay"
|
||||
KMACHINE_crownbay = "crownbay"
|
||||
KBRANCH_crownbay = "standard/default/crownbay"
|
||||
|
||||
COMPATIBLE_MACHINE_crownbay-noemgd = "crownbay-noemgd"
|
||||
KMACHINE_crownbay-noemgd = "crownbay"
|
||||
KBRANCH_crownbay-noemgd = "standard/default/crownbay"
|
||||
</literallayout>
|
||||
The <filename>KBRANCH_*</filename> statements identify the kernel branch to
|
||||
use when building for the Crown Bay BSP.
|
||||
In this case there are two identical statements: one for each type of
|
||||
Crown Bay machine.
|
||||
</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry id='var-KERNEL_FEATURES'><glossterm>KERNEL_FEATURES</glossterm>
|
||||
<glossdef>
|
||||
<para>Includes additional metadata from the Yocto Project kernel Git repository.
|
||||
In the OpenEmbedded build system, the default Board Support Packages (BSPs)
|
||||
<para>Includes additional metadata from the Linux Yocto kernel Git repository.
|
||||
In the Yocto Project build system, the default Board Support Packages (BSPs)
|
||||
metadata is provided through
|
||||
the <filename>KMACHINE</filename> and <filename>KBRANCH</filename> variables.
|
||||
You can use the <filename>KERNEL_FEATURES</filename> variable to further
|
||||
@@ -1106,7 +1049,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
In this way, you can provide validated, but optional, sets of kernel
|
||||
configurations and features.</para>
|
||||
<para>For example, the following adds <filename>netfilter</filename> to all
|
||||
the Yocto Project kernels and adds sound support to the <filename>qemux86</filename>
|
||||
the Linux Yocto kernels and adds sound support to the <filename>qemux86</filename>
|
||||
machine:
|
||||
<literallayout class='monospaced'>
|
||||
# Add netfilter to all linux-yocto kernels
|
||||
@@ -1128,94 +1071,6 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
<glossentry id='var-KMACHINE'><glossterm>KMACHINE</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
The machine as known by the kernel.
|
||||
Sometimes the machine name used by the kernel does not match the machine name
|
||||
used by the OpenEmbedded build system.
|
||||
For example, the machine name that the OpenEmbedded build system understands as
|
||||
<filename>qemuarm</filename> goes by a different name in the Linux Yocto kernel.
|
||||
The kernel understands that machine as <filename>arm_versatile926ejs</filename>.
|
||||
For cases like these, the <filename>KMACHINE</filename> variable maps the
|
||||
kernel machine name to the OpenEmbedded build system machine name.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Kernel machine names are initially defined in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#local-kernel-files'>Yocto Project Kernel</ulink> in
|
||||
the <filename>meta/cfg/kernel-cache/bsp/<bsp_name>/<bsp-name>-<kernel-type>.scc</filename> file.
|
||||
For example, in the <filename>linux-yocto-3.4</filename> kernel in the
|
||||
<filename>meta/cfg/kernel-cache/bsp/cedartrail/cedartrail-standard.scc</filename> file,
|
||||
has the following:
|
||||
<literallayout class='monospaced'>
|
||||
define KMACHINE cedartrail
|
||||
define KTYPE standard
|
||||
define KARCH i386
|
||||
|
||||
include ktypes/standard
|
||||
branch cedartrail
|
||||
|
||||
include cedartrail.scc
|
||||
</literallayout>
|
||||
You can see that the kernel understands the machine name for the Cedar Trail BSP as
|
||||
<filename>cedartrail</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you look in the Cedar Trail BSP layer in the <filename>meta-intel</filename> source
|
||||
repository at <filename>meta-cedartrail/recipes-kernel/linux/linux-yocto_3.0.bbappend</filename>,
|
||||
you will find the following statements among others:
|
||||
<literallayout class='monospaced'>
|
||||
COMPATIBLE_MACHINE_cedartrail = "cedartrail"
|
||||
KMACHINE_cedartrail = "cedartrail"
|
||||
KBRANCH_cedartrail = "yocto/standard/cedartrail"
|
||||
KERNEL_FEATURES_append_cedartrail += "bsp/cedartrail/cedartrail-pvr-merge.scc"
|
||||
KERNEL_FEATURES_append_cedartrail += "cfg/efi-ext.scc"
|
||||
|
||||
COMPATIBLE_MACHINE_cedartrail-nopvr = "cedartrail"
|
||||
KMACHINE_cedartrail-nopvr = "cedartrail"
|
||||
KBRANCH_cedartrail-nopvr = "yocto/standard/cedartrail"
|
||||
KERNEL_FEATURES_append_cedartrail-nopvr += " cfg/smp.scc"
|
||||
</literallayout>
|
||||
The <filename>KMACHINE</filename> statements in the kernel's append file make sure that
|
||||
the OpenEmbedded build system and the Yocto Linux kernel understand the same machine
|
||||
names.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This append file uses two <filename>KMACHINE</filename> statements.
|
||||
The first is not really necessary but does ensure that the machine known to the
|
||||
OpenEmbedded build system as <filename>cedartrail</filename> maps to the machine
|
||||
in the kernel also known as <filename>cedartrail</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
KMACHINE_cedartrail = "cedartrail"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The second statement is a good example of why the <filename>KMACHINE</filename> variable
|
||||
is needed.
|
||||
In this example, the OpenEmbedded build system uses the <filename>cedartrail-nopvr</filename>
|
||||
machine name to refer to the Cedar Trail BSP that does not support the propriatory
|
||||
PowerVR driver.
|
||||
The kernel, however, uses the machine name <filename>cedartrail</filename>.
|
||||
Thus, the append file must map the <filename>cedartrail-nopvr</filename> machine name to
|
||||
the kernel's <filename>cedartrail</filename> name:
|
||||
<literallayout class='monospaced'>
|
||||
KMACHINE_cedartrail-nopvr = "cedartrail"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
BSPs that ship with the Yocto Project release provide all mappings between the Yocto
|
||||
Project kernel machine names and the OpenEmbedded machine names.
|
||||
Be sure to use the <filename>KMACHINE</filename> if you create a BSP and the machine
|
||||
name you use is different than that used in the kernel.
|
||||
</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
|
||||
</glossdiv>
|
||||
|
||||
<glossdiv id='var-glossary-l'><title>L</title>
|
||||
@@ -1282,7 +1137,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-LICENSE_DIR'><glossterm>LICENSE_DIR</glossterm>
|
||||
<glossdef>
|
||||
<para>Path to additional licenses used during the build.
|
||||
By default, the OpenEmbedded build system uses <filename>COMMON_LICENSE_DIR</filename>
|
||||
By default, the Yocto Project uses <filename>COMMON_LICENSE_DIR</filename>
|
||||
to define the directory that holds common license text used during the build.
|
||||
The <filename>LICENSE_DIR</filename> variable allows you to extend that
|
||||
location to other areas that have additional licenses:
|
||||
@@ -1486,8 +1341,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-PACKAGE_CLASSES'><glossterm>PACKAGE_CLASSES</glossterm>
|
||||
<glossdef>
|
||||
<para>This variable, which is set in the <filename>local.conf</filename> configuration
|
||||
file found in the <filename>conf</filename> folder of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>,
|
||||
file found in the Yocto Project file's <filename>conf</filename> directory,
|
||||
specifies the package manager to use when packaging data.
|
||||
You can provide one or more arguments for the variable with the first
|
||||
argument being the package manager used to create images:
|
||||
@@ -1680,7 +1534,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<filename><link linkend='var-RDEPENDS'>RDEPENDS</link></filename> variable.
|
||||
</para>
|
||||
<para>
|
||||
The OpenEmbedded build process automatically installs the list of packages
|
||||
The Yocto Project build process automatically installs the list of packages
|
||||
as part of the built package.
|
||||
However, you can remove them later if you want.
|
||||
If, during the build, a package from the list cannot be found, the build
|
||||
@@ -1718,8 +1572,8 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-S'><glossterm>S</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
The location in the <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
where unpacked package source code resides.
|
||||
The location in the <ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>
|
||||
Yocto Project Build Directory</ulink> where unpacked package source code resides.
|
||||
This location is within the working directory
|
||||
(<filename><link linkend='var-WORKDIR'>WORKDIR</link></filename>), which
|
||||
is not static.
|
||||
@@ -1731,10 +1585,9 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
${WORKDIR}/${PN}-${PV}
|
||||
</literallayout>
|
||||
As an example, assume a
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink> top-level
|
||||
folder named <filename>poky</filename>
|
||||
and a default <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
at <filename>poky/build</filename>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>
|
||||
Yocto Project Files</ulink> top-level directory named <filename>poky</filename>
|
||||
and a default Yocto Project Build Directory of <filename>poky/build</filename>.
|
||||
In this case, the working directory the build system uses to build
|
||||
the <filename>db</filename> package is the following:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -1808,10 +1661,10 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossdef>
|
||||
<para></para>
|
||||
<para>
|
||||
By default, the OpenEmbedded build system automatically detects whether
|
||||
By default, the Yocto Project automatically detects whether
|
||||
<filename><link linkend='var-SRC_URI'>SRC_URI</link></filename>
|
||||
contains files that are machine-specific.
|
||||
If so, the build system automatically changes
|
||||
If so, the Yocto Project automatically changes
|
||||
<filename><link linkend='var-PACKAGE_ARCH'>PACKAGE_ARCH</link></filename>.
|
||||
Setting this variable to "0" disables this behavior.
|
||||
</para>
|
||||
@@ -1875,7 +1728,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-TARGET_ARCH'><glossterm>TARGET_ARCH</glossterm>
|
||||
<glossdef>
|
||||
<para>The architecture of the device being built.
|
||||
While a number of values are possible, the OpenEmbedded build system primarily supports
|
||||
While a number of values are possible, the Yocto Project primarily supports
|
||||
<filename>arm</filename> and <filename>i586</filename>.</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
@@ -1937,18 +1790,15 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
</para>
|
||||
<para>
|
||||
The <filename>TCMODE</filename> variable selects the external toolchain
|
||||
built using the OpenEmbedded build system or a few supported combinations of
|
||||
built from the Yocto Project or a few supported combinations of
|
||||
the upstream GCC or CodeSourcery Labs toolchain.
|
||||
The variable determines which of the <filename>tcmode-*</filename> files in
|
||||
the <filename>meta/conf/distro/include</filename> directory, which is found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>,
|
||||
is used.
|
||||
The variable determines which of the files in
|
||||
<filename>meta/conf/distro/include/tcmode-*</filename> is used.
|
||||
</para>
|
||||
<para>
|
||||
By default, <filename>TCMODE</filename> is set to "default", which
|
||||
chooses the <filename>tcmode-default.inc</filename> file.
|
||||
The variable is similar to
|
||||
<link linkend='var-TCLIBC'><filename>TCLIBC</filename></link>, which controls
|
||||
chooses <filename>tcmode-default.inc</filename>.
|
||||
The variable is similar to <filename>TCLIBC</filename>, which controls
|
||||
the variant of the GNU standard C library (<filename>libc</filename>)
|
||||
used during the build process: <filename>eglibc</filename> or <filename>uclibc</filename>.
|
||||
</para>
|
||||
@@ -1958,18 +1808,20 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-TMPDIR'><glossterm>TMPDIR</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
This variable is the temporary directory the OpenEmbedded build system
|
||||
This variable is the temporary directory the Yocto Project build system
|
||||
uses when it does its work building images.
|
||||
By default, the <filename>TMPDIR</filename> variable is named
|
||||
<filename>tmp</filename> within the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>
|
||||
Yocto Project Build Directory</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you want to establish this directory in a location other than the
|
||||
default, you can uncomment the following statement in the
|
||||
<filename>conf/local.conf</filename> file in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>:
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>
|
||||
Yocto Project Files</ulink>:
|
||||
<literallayout class='monospaced'>
|
||||
#TMPDIR = "${TOPDIR}/tmp"
|
||||
</literallayout>
|
||||
@@ -1981,9 +1833,10 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossdef>
|
||||
<para>
|
||||
This variable is the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>
|
||||
Yocto Project Build Directory</ulink>.
|
||||
BitBake automatically sets this variable.
|
||||
The OpenEmbedded build system uses the build directory when building images.
|
||||
The Yocto Project build system uses the build directory when building images.
|
||||
</para>
|
||||
</glossdef>
|
||||
</glossentry>
|
||||
@@ -2001,7 +1854,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<glossentry id='var-WORKDIR'><glossterm>WORKDIR</glossterm>
|
||||
<glossdef>
|
||||
<para>
|
||||
The pathname of the working directory in which the OpenEmbedded build system
|
||||
The pathname of the working directory in which the Yocto Project build system
|
||||
builds packages.
|
||||
This directory is located within the
|
||||
<link linkend='var-TMPDIR'><filename>TMPDIR</filename></link> directory structure and changes
|
||||
@@ -2028,10 +1881,11 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
${TMPDIR}/work/${PACKAGE_ARCH}-poky-${TARGET_OS}/${PN}-${PV}-${PR}
|
||||
</literallayout>
|
||||
As an example, assume a
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink> top-level
|
||||
folder name <filename>poky</filename> and a default
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>
|
||||
at <filename>poky/build</filename>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-files'>
|
||||
Yocto Project Files</ulink> top-level directory named <filename>poky</filename>
|
||||
and a default
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-build-directory'>
|
||||
Yocto Project Build Directory</ulink> of <filename>poky/build</filename>.
|
||||
In this case, the working directory the build system uses to build
|
||||
the <filename>v86d</filename> package is the following:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -2045,9 +1899,9 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<literallayout class='monospaced'>
|
||||
${TMPDIR}/work/${MACHINE}-poky-${TARGET_OS}/${PN}-${PV}-${PR}
|
||||
</literallayout>
|
||||
As an example, again assume a source directory top-level folder
|
||||
named <filename>poky</filename> and a default build directory
|
||||
at <filename>poky/build</filename>.
|
||||
As an example, again assume a Yocto Project Files top-level directory
|
||||
named <filename>poky</filename> and a default Yocto Project build directory
|
||||
of <filename>poky/build</filename>.
|
||||
In this case, the working directory the build system uses to build
|
||||
the <filename>acl</filename> package, which is dependent on a
|
||||
MIPS-based device, is the following:
|
||||
@@ -2070,7 +1924,7 @@ recipes-graphics/xorg-font/xorg-font-common.inc:INC_PR = "r2"
|
||||
<!-- </glossdiv>-->
|
||||
|
||||
</glossary>
|
||||
</chapter>
|
||||
</appendix>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user