Compare commits
1 Commits
danny
...
1.3_M2.fin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20dc7d2766 |
7
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
bitbake
|
||||
*.pyc
|
||||
*.pyo
|
||||
/*.patch
|
||||
@@ -8,10 +9,10 @@ scripts/oe-git-proxy-socks
|
||||
sources/
|
||||
meta-*
|
||||
!meta-skeleton
|
||||
!meta-hob
|
||||
!meta-demoapps
|
||||
*.swp
|
||||
*.orig
|
||||
*.rej
|
||||
*~
|
||||
!meta-yocto
|
||||
!meta-yocto-bsp
|
||||
|
||||
|
||||
|
||||
20
README
@@ -27,23 +27,3 @@ DISTRO = "") and contains only emulated machine support.
|
||||
For information about OpenEmbedded, see the OpenEmbedded website:
|
||||
http://www.openembedded.org/
|
||||
|
||||
Where to Send Patches
|
||||
=====================
|
||||
|
||||
As Poky is an integration repository, patches against the various components
|
||||
should be sent to their respective upstreams.
|
||||
|
||||
bitbake:
|
||||
bitbake-devel@lists.openembedded.org
|
||||
|
||||
meta-yocto:
|
||||
poky@yoctoproject.org
|
||||
|
||||
Most everything else should be sent to the OpenEmbedded Core mailing list. If
|
||||
in doubt, check the oe-core git repository for the content you intend to modify.
|
||||
Before sending, be sure the patches apply cleanly to the current oe-core git
|
||||
repository.
|
||||
openembedded-core@lists.openembedded.org
|
||||
|
||||
Note: The scripts directory should be treated with extra care as it is a mix
|
||||
of oe-core and poky-specific files.
|
||||
|
||||
@@ -40,17 +40,9 @@ from bb import cooker
|
||||
from bb import ui
|
||||
from bb import server
|
||||
|
||||
__version__ = "1.16.0"
|
||||
__version__ = "1.15.2"
|
||||
logger = logging.getLogger("BitBake")
|
||||
|
||||
# Unbuffer stdout to avoid log truncation in the event
|
||||
# of an unorderly exit as well as to provide timely
|
||||
# updates to log files for use with tail
|
||||
try:
|
||||
if sys.stdout.name == '<stdout>':
|
||||
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
|
||||
except:
|
||||
pass
|
||||
|
||||
class BBConfiguration(object):
|
||||
"""
|
||||
@@ -78,7 +70,7 @@ def get_ui(config):
|
||||
return getattr(module, interface).main
|
||||
except AttributeError:
|
||||
sys.exit("FATAL: Invalid user interface '%s' specified.\n"
|
||||
"Valid interfaces: depexp, goggle, ncurses, hob, knotty [default]." % interface)
|
||||
"Valid interfaces: depexp, goggle, ncurses, hob, knotty [default], knotty2." % interface)
|
||||
|
||||
|
||||
# Display bitbake/OE warnings via the BitBake.Warnings logger, ignoring others"""
|
||||
@@ -150,7 +142,7 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
parser.add_option("-p", "--parse-only", help = "quit after parsing the BB files (developers only)",
|
||||
action = "store_true", dest = "parse_only", default = False)
|
||||
|
||||
parser.add_option("-s", "--show-versions", help = "show current and preferred versions of all recipes",
|
||||
parser.add_option("-s", "--show-versions", help = "show current and preferred versions of all packages",
|
||||
action = "store_true", dest = "show_versions", default = False)
|
||||
|
||||
parser.add_option("-e", "--environment", help = "show the global or per-package environment (this is what used to be bbread)",
|
||||
@@ -182,8 +174,6 @@ Default BBFILES are the .bb files in the current directory.""")
|
||||
|
||||
parser.add_option("-B", "--bind", help = "The name/address for the bitbake server to bind to",
|
||||
action = "store", dest = "bind", default = False)
|
||||
parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks, forces builds",
|
||||
action = "store_true", dest = "nosetscene", default = False)
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
|
||||
configuration = BBConfiguration(options)
|
||||
|
||||
@@ -1,102 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# bitbake-diffsigs
|
||||
# BitBake task signature data comparison utility
|
||||
#
|
||||
# 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 sys
|
||||
import warnings
|
||||
import fnmatch
|
||||
import optparse
|
||||
import logging
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
|
||||
|
||||
import bb.tinfoil
|
||||
import bb.siggen
|
||||
|
||||
logger = logging.getLogger('BitBake')
|
||||
|
||||
def find_compare_task(bbhandler, pn, taskname):
|
||||
""" Find the most recent signature files for the specified PN/task and compare them """
|
||||
|
||||
if not hasattr(bb.siggen, 'find_siginfo'):
|
||||
logger.error('Metadata does not support finding signature data files')
|
||||
sys.exit(1)
|
||||
|
||||
filedates = bb.siggen.find_siginfo(pn, taskname, None, bbhandler.config_data)
|
||||
latestfiles = sorted(filedates.keys(), key=lambda f: filedates[f])[-2:]
|
||||
if not latestfiles:
|
||||
logger.error('No sigdata files found matching %s %s' % (pn, taskname))
|
||||
sys.exit(1)
|
||||
elif len(latestfiles) < 2:
|
||||
logger.error('Only one matching sigdata file found for the specified task (%s %s)' % (pn, taskname))
|
||||
sys.exit(1)
|
||||
else:
|
||||
# Define recursion callback
|
||||
def recursecb(key, hash1, hash2):
|
||||
hashes = [hash1, hash2]
|
||||
hashfiles = bb.siggen.find_siginfo(key, None, hashes, bbhandler.config_data)
|
||||
|
||||
recout = []
|
||||
if len(hashfiles) == 2:
|
||||
out2 = bb.siggen.compare_sigfiles(hashfiles[hash1], hashfiles[hash2], recursecb)
|
||||
recout.extend(list(' ' + l for l in out2))
|
||||
else:
|
||||
recout.append("Unable to find matching sigdata for %s with hashes %s or %s" % (key, hash1, hash2))
|
||||
|
||||
return recout
|
||||
|
||||
# Recurse into signature comparison
|
||||
output = bb.siggen.compare_sigfiles(latestfiles[0], latestfiles[1], recursecb)
|
||||
if output:
|
||||
print '\n'.join(output)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
|
||||
parser = optparse.OptionParser(
|
||||
usage = """
|
||||
%prog -t recipename taskname
|
||||
%prog sigdatafile1 sigdatafile2
|
||||
%prog sigdatafile1""")
|
||||
|
||||
parser.add_option("-t", "--task",
|
||||
help = "find the signature data files for last two runs of the specified task and compare them",
|
||||
action="store_true", dest="taskmode")
|
||||
|
||||
options, args = parser.parse_args(sys.argv)
|
||||
|
||||
if len(args) == 1:
|
||||
parser.print_help()
|
||||
if len(sys.argv) > 2:
|
||||
bb.siggen.compare_sigfiles(sys.argv[1], sys.argv[2])
|
||||
else:
|
||||
tinfoil = bb.tinfoil.Tinfoil()
|
||||
if options.taskmode:
|
||||
if len(args) < 3:
|
||||
logger.error("Please specify a recipe and task name")
|
||||
sys.exit(1)
|
||||
tinfoil.prepare(config_only = True)
|
||||
find_compare_task(tinfoil, args[1], args[2])
|
||||
else:
|
||||
if len(args) == 2:
|
||||
output = bb.siggen.dump_sigfile(sys.argv[1])
|
||||
else:
|
||||
output = bb.siggen.compare_sigfiles(sys.argv[1], sys.argv[2])
|
||||
|
||||
if output:
|
||||
print '\n'.join(output)
|
||||
bb.siggen.dump_sigfile(sys.argv[1])
|
||||
|
||||
@@ -6,6 +6,4 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), '
|
||||
|
||||
import bb.siggen
|
||||
|
||||
output = bb.siggen.dump_sigfile(sys.argv[1])
|
||||
if output:
|
||||
print '\n'.join(output)
|
||||
bb.siggen.dump_sigfile(sys.argv[1])
|
||||
|
||||
@@ -6,22 +6,10 @@
|
||||
|
||||
# Copyright (C) 2011 Mentor Graphics Corporation
|
||||
# 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 cmd
|
||||
import logging
|
||||
import warnings
|
||||
import os
|
||||
import sys
|
||||
import fnmatch
|
||||
@@ -35,14 +23,26 @@ import bb.cache
|
||||
import bb.cooker
|
||||
import bb.providers
|
||||
import bb.utils
|
||||
import bb.tinfoil
|
||||
from bb.cooker import state
|
||||
import bb.fetch2
|
||||
|
||||
|
||||
logger = logging.getLogger('BitBake')
|
||||
|
||||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||
|
||||
def main(args):
|
||||
cmds = Commands()
|
||||
# Set up logging
|
||||
console = logging.StreamHandler(sys.stdout)
|
||||
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
|
||||
bb.msg.addDefaultlogFilter(console)
|
||||
console.setFormatter(format)
|
||||
logger.addHandler(console)
|
||||
|
||||
initialenv = os.environ.copy()
|
||||
bb.utils.clean_environment()
|
||||
|
||||
cmds = Commands(initialenv)
|
||||
if args:
|
||||
# Allow user to specify e.g. show-layers instead of show_layers
|
||||
args = [args[0].replace('-', '_')] + args[1:]
|
||||
@@ -53,11 +53,42 @@ def main(args):
|
||||
|
||||
|
||||
class Commands(cmd.Cmd):
|
||||
def __init__(self):
|
||||
def __init__(self, initialenv):
|
||||
cmd.Cmd.__init__(self)
|
||||
self.bbhandler = bb.tinfoil.Tinfoil()
|
||||
self.returncode = 0
|
||||
self.bblayers = (self.bbhandler.config_data.getVar('BBLAYERS', True) or "").split()
|
||||
self.config = Config(parse_only=True)
|
||||
self.cooker = bb.cooker.BBCooker(self.config,
|
||||
self.register_idle_function,
|
||||
initialenv)
|
||||
self.config_data = self.cooker.configuration.data
|
||||
bb.providers.logger.setLevel(logging.ERROR)
|
||||
self.cooker_data = None
|
||||
self.bblayers = (self.config_data.getVar('BBLAYERS', True) or "").split()
|
||||
|
||||
def register_idle_function(self, function, data):
|
||||
pass
|
||||
|
||||
def prepare_cooker(self):
|
||||
sys.stderr.write("Parsing recipes..")
|
||||
logger.setLevel(logging.WARNING)
|
||||
|
||||
try:
|
||||
while self.cooker.state in (state.initial, state.parsing):
|
||||
self.cooker.updateCache()
|
||||
except KeyboardInterrupt:
|
||||
self.cooker.shutdown()
|
||||
self.cooker.updateCache()
|
||||
sys.exit(2)
|
||||
|
||||
logger.setLevel(logging.INFO)
|
||||
sys.stderr.write("done.\n")
|
||||
|
||||
self.cooker_data = self.cooker.status
|
||||
self.cooker_data.appends = self.cooker.appendlist
|
||||
|
||||
def check_prepare_cooker(self):
|
||||
if not self.cooker_data:
|
||||
self.prepare_cooker()
|
||||
|
||||
def default(self, line):
|
||||
"""Handle unrecognised commands"""
|
||||
@@ -82,13 +113,14 @@ class Commands(cmd.Cmd):
|
||||
|
||||
def do_show_layers(self, args):
|
||||
"""show current configured layers"""
|
||||
self.bbhandler.prepare(config_only = True)
|
||||
self.check_prepare_cooker()
|
||||
logger.plain('')
|
||||
logger.plain("%s %s %s" % ("layer".ljust(20), "path".ljust(40), "priority"))
|
||||
logger.plain('=' * 74)
|
||||
for layerdir in self.bblayers:
|
||||
layername = self.get_layer_name(layerdir)
|
||||
layerpri = 0
|
||||
for layer, _, regex, pri in self.bbhandler.cooker.status.bbfile_config_priorities:
|
||||
for layer, _, regex, pri in self.cooker.status.bbfile_config_priorities:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
layerpri = pri
|
||||
break
|
||||
@@ -106,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]
|
||||
|
||||
@@ -119,7 +151,7 @@ Options:
|
||||
recipes with the ones they overlay indented underneath
|
||||
-s only list overlayed recipes where the version is the same
|
||||
"""
|
||||
self.bbhandler.prepare()
|
||||
self.check_prepare_cooker()
|
||||
|
||||
show_filenames = False
|
||||
show_same_ver_only = False
|
||||
@@ -151,7 +183,7 @@ Options:
|
||||
# factor - however, each layer.conf is free to either prepend or append to
|
||||
# BBPATH (or indeed do crazy stuff with it). Thus the order in BBPATH might
|
||||
# not be exactly the order present in bblayers.conf either.
|
||||
bbpath = str(self.bbhandler.config_data.getVar('BBPATH', True))
|
||||
bbpath = str(self.config_data.getVar('BBPATH', True))
|
||||
overlayed_class_found = False
|
||||
for (classfile, classdirs) in classes.items():
|
||||
if len(classdirs) > 1:
|
||||
@@ -202,7 +234,7 @@ Options:
|
||||
-m only list where multiple recipes (in the same layer or different
|
||||
layers) exist for the same recipe name
|
||||
"""
|
||||
self.bbhandler.prepare()
|
||||
self.check_prepare_cooker()
|
||||
|
||||
show_filenames = False
|
||||
show_multi_provider_only = False
|
||||
@@ -224,15 +256,15 @@ Options:
|
||||
|
||||
|
||||
def list_recipes(self, title, pnspec, show_overlayed_only, show_same_ver_only, show_filenames, show_multi_provider_only):
|
||||
pkg_pn = self.bbhandler.cooker.status.pkg_pn
|
||||
(latest_versions, preferred_versions) = bb.providers.findProviders(self.bbhandler.cooker.configuration.data, self.bbhandler.cooker.status, pkg_pn)
|
||||
allproviders = bb.providers.allProviders(self.bbhandler.cooker.status)
|
||||
pkg_pn = self.cooker.status.pkg_pn
|
||||
(latest_versions, preferred_versions) = bb.providers.findProviders(self.cooker.configuration.data, self.cooker.status, pkg_pn)
|
||||
allproviders = bb.providers.allProviders(self.cooker.status)
|
||||
|
||||
# Ensure we list skipped recipes
|
||||
# We are largely guessing about PN, PV and the preferred version here,
|
||||
# but we have no choice since skipped recipes are not fully parsed
|
||||
skiplist = self.bbhandler.cooker.skiplist.keys()
|
||||
skiplist.sort( key=lambda fileitem: self.bbhandler.cooker.calc_bbfile_priority(fileitem) )
|
||||
skiplist = self.cooker.skiplist.keys()
|
||||
skiplist.sort( key=lambda fileitem: self.cooker.calc_bbfile_priority(fileitem) )
|
||||
skiplist.reverse()
|
||||
for fn in skiplist:
|
||||
recipe_parts = os.path.splitext(os.path.basename(fn))[0].split('_')
|
||||
@@ -340,7 +372,7 @@ build results (as the layer priority order has effectively changed).
|
||||
logger.error('Directory %s exists and is non-empty, please clear it out first' % outputdir)
|
||||
return
|
||||
|
||||
self.bbhandler.prepare()
|
||||
self.check_prepare_cooker()
|
||||
layers = self.bblayers
|
||||
if len(arglist) > 2:
|
||||
layernames = arglist[:-1]
|
||||
@@ -370,8 +402,8 @@ build results (as the layer priority order has effectively changed).
|
||||
appended_recipes = []
|
||||
for layer in layers:
|
||||
overlayed = []
|
||||
for f in self.bbhandler.cooker.overlayed.iterkeys():
|
||||
for of in self.bbhandler.cooker.overlayed[f]:
|
||||
for f in self.cooker.overlayed.iterkeys():
|
||||
for of in self.cooker.overlayed[f]:
|
||||
if of.startswith(layer):
|
||||
overlayed.append(of)
|
||||
|
||||
@@ -395,8 +427,8 @@ build results (as the layer priority order has effectively changed).
|
||||
logger.warn('Overwriting file %s', fdest)
|
||||
bb.utils.copyfile(f1full, fdest)
|
||||
if ext == '.bb':
|
||||
if f1 in self.bbhandler.cooker.appendlist:
|
||||
appends = self.bbhandler.cooker.appendlist[f1]
|
||||
if f1 in self.cooker_data.appends:
|
||||
appends = self.cooker_data.appends[f1]
|
||||
if appends:
|
||||
logger.plain(' Applying appends to %s' % fdest )
|
||||
for appendname in appends:
|
||||
@@ -405,9 +437,9 @@ build results (as the layer priority order has effectively changed).
|
||||
appended_recipes.append(f1)
|
||||
|
||||
# Take care of when some layers are excluded and yet we have included bbappends for those recipes
|
||||
for recipename in self.bbhandler.cooker.appendlist.iterkeys():
|
||||
for recipename in self.cooker_data.appends.iterkeys():
|
||||
if recipename not in appended_recipes:
|
||||
appends = self.bbhandler.cooker.appendlist[recipename]
|
||||
appends = self.cooker_data.appends[recipename]
|
||||
first_append = None
|
||||
for appendname in appends:
|
||||
layer = layer_path_match(appendname)
|
||||
@@ -425,14 +457,14 @@ build results (as the layer priority order has effectively changed).
|
||||
# have come from)
|
||||
first_regex = None
|
||||
layerdir = layers[0]
|
||||
for layername, pattern, regex, _ in self.bbhandler.cooker.status.bbfile_config_priorities:
|
||||
for layername, pattern, regex, _ in self.cooker.status.bbfile_config_priorities:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
first_regex = regex
|
||||
break
|
||||
|
||||
if first_regex:
|
||||
# Find the BBFILES entries that match (which will have come from this conf/layer.conf file)
|
||||
bbfiles = str(self.bbhandler.config_data.getVar('BBFILES', True)).split()
|
||||
bbfiles = str(self.config_data.getVar('BBFILES', True)).split()
|
||||
bbfiles_layer = []
|
||||
for item in bbfiles:
|
||||
if first_regex.match(item):
|
||||
@@ -455,7 +487,7 @@ build results (as the layer priority order has effectively changed).
|
||||
logger.warning("File %s does not match the flattened layer's BBFILES setting, you may need to edit conf/layer.conf or move the file elsewhere" % f1full)
|
||||
|
||||
def get_file_layer(self, filename):
|
||||
for layer, _, regex, _ in self.bbhandler.cooker.status.bbfile_config_priorities:
|
||||
for layer, _, regex, _ in self.cooker.status.bbfile_config_priorities:
|
||||
if regex.match(filename):
|
||||
for layerdir in self.bblayers:
|
||||
if regex.match(os.path.join(layerdir, 'test')):
|
||||
@@ -481,14 +513,14 @@ usage: show-appends
|
||||
|
||||
Recipes are listed with the bbappends that apply to them as subitems.
|
||||
"""
|
||||
self.bbhandler.prepare()
|
||||
if not self.bbhandler.cooker.appendlist:
|
||||
self.check_prepare_cooker()
|
||||
if not self.cooker_data.appends:
|
||||
logger.plain('No append files found')
|
||||
return
|
||||
|
||||
logger.plain('=== Appended recipes ===')
|
||||
logger.plain('State of append files:')
|
||||
|
||||
pnlist = list(self.bbhandler.cooker_data.pkg_pn.keys())
|
||||
pnlist = list(self.cooker_data.pkg_pn.keys())
|
||||
pnlist.sort()
|
||||
for pn in pnlist:
|
||||
self.show_appends_for_pn(pn)
|
||||
@@ -496,19 +528,19 @@ Recipes are listed with the bbappends that apply to them as subitems.
|
||||
self.show_appends_for_skipped()
|
||||
|
||||
def show_appends_for_pn(self, pn):
|
||||
filenames = self.bbhandler.cooker_data.pkg_pn[pn]
|
||||
filenames = self.cooker_data.pkg_pn[pn]
|
||||
|
||||
best = bb.providers.findBestProvider(pn,
|
||||
self.bbhandler.cooker.configuration.data,
|
||||
self.bbhandler.cooker_data,
|
||||
self.bbhandler.cooker_data.pkg_pn)
|
||||
self.cooker.configuration.data,
|
||||
self.cooker_data,
|
||||
self.cooker_data.pkg_pn)
|
||||
best_filename = os.path.basename(best[3])
|
||||
|
||||
self.show_appends_output(filenames, best_filename)
|
||||
|
||||
def show_appends_for_skipped(self):
|
||||
filenames = [os.path.basename(f)
|
||||
for f in self.bbhandler.cooker.skiplist.iterkeys()]
|
||||
for f in self.cooker.skiplist.iterkeys()]
|
||||
self.show_appends_output(filenames, None, " (skipped)")
|
||||
|
||||
def show_appends_output(self, filenames, best_filename, name_suffix = ''):
|
||||
@@ -534,7 +566,7 @@ Recipes are listed with the bbappends that apply to them as subitems.
|
||||
continue
|
||||
|
||||
basename = os.path.basename(filename)
|
||||
appends = self.bbhandler.cooker.appendlist.get(basename)
|
||||
appends = self.cooker_data.appends.get(basename)
|
||||
if appends:
|
||||
appended.append((basename, list(appends)))
|
||||
else:
|
||||
@@ -542,5 +574,22 @@ Recipes are listed with the bbappends that apply to them as subitems.
|
||||
return appended, notappended
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self, **options):
|
||||
self.pkgs_to_build = []
|
||||
self.debug_domains = []
|
||||
self.extra_assume_provided = []
|
||||
self.prefile = []
|
||||
self.postfile = []
|
||||
self.debug = 0
|
||||
self.__dict__.update(options)
|
||||
|
||||
def __getattr__(self, attribute):
|
||||
try:
|
||||
return super(Config, self).__getattribute__(attribute)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv[1:]) or 0)
|
||||
|
||||
@@ -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:]))
|
||||
|
||||
@@ -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.16.0"
|
||||
__version__ = "1.15.2"
|
||||
|
||||
import sys
|
||||
if sys.version_info < (2, 6, 0):
|
||||
|
||||
@@ -29,7 +29,6 @@ import os
|
||||
import sys
|
||||
import logging
|
||||
import shlex
|
||||
import glob
|
||||
import bb
|
||||
import bb.msg
|
||||
import bb.process
|
||||
@@ -73,7 +72,7 @@ class TaskBase(event.Event):
|
||||
self._task = t
|
||||
self._package = d.getVar("PF", True)
|
||||
event.Event.__init__(self)
|
||||
self._message = "recipe %s: task %s: %s" % (d.getVar("PF", True), t, self.getDisplayName())
|
||||
self._message = "package %s: task %s: %s" % (d.getVar("PF", True), t, self.getDisplayName())
|
||||
|
||||
def getTask(self):
|
||||
return self._task
|
||||
@@ -465,55 +464,15 @@ def stamp_internal(taskname, d, file_name):
|
||||
|
||||
stamp = bb.parse.siggen.stampfile(stamp, file_name, taskname, extrainfo)
|
||||
|
||||
stampdir = os.path.dirname(stamp)
|
||||
if bb.parse.cached_mtime_noerror(stampdir) == 0:
|
||||
bb.utils.mkdirhier(stampdir)
|
||||
bb.utils.mkdirhier(os.path.dirname(stamp))
|
||||
|
||||
return stamp
|
||||
|
||||
def stamp_cleanmask_internal(taskname, d, file_name):
|
||||
"""
|
||||
Internal stamp helper function to generate stamp cleaning mask
|
||||
Returns the stamp path+filename
|
||||
|
||||
In the bitbake core, d can be a CacheData and file_name will be set.
|
||||
When called in task context, d will be a data store, file_name will not be set
|
||||
"""
|
||||
taskflagname = taskname
|
||||
if taskname.endswith("_setscene") and taskname != "do_setscene":
|
||||
taskflagname = taskname.replace("_setscene", "")
|
||||
|
||||
if file_name:
|
||||
stamp = d.stamp_base_clean[file_name].get(taskflagname) or d.stampclean[file_name]
|
||||
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
|
||||
else:
|
||||
stamp = d.getVarFlag(taskflagname, 'stamp-base-clean', True) or d.getVar('STAMPCLEAN', True)
|
||||
file_name = d.getVar('BB_FILENAME', True)
|
||||
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
|
||||
|
||||
if not stamp:
|
||||
return []
|
||||
|
||||
cleanmask = bb.parse.siggen.stampcleanmask(stamp, file_name, taskname, extrainfo)
|
||||
|
||||
return [cleanmask, cleanmask.replace(taskflagname, taskflagname + "_setscene")]
|
||||
|
||||
def make_stamp(task, d, file_name = None):
|
||||
"""
|
||||
Creates/updates a stamp for a given task
|
||||
(d can be a data dict or dataCache)
|
||||
"""
|
||||
cleanmask = stamp_cleanmask_internal(task, d, file_name)
|
||||
for mask in cleanmask:
|
||||
for name in glob.glob(mask):
|
||||
# Preserve sigdata files in the stamps directory
|
||||
if "sigdata" in name:
|
||||
continue
|
||||
# Preserve taint files in the stamps directory
|
||||
if name.endswith('.taint'):
|
||||
continue
|
||||
os.unlink(name)
|
||||
|
||||
stamp = stamp_internal(task, d, file_name)
|
||||
# Remove the file and recreate to force timestamp
|
||||
# change on broken NFS filesystems
|
||||
|
||||
@@ -43,7 +43,7 @@ except ImportError:
|
||||
logger.info("Importing cPickle failed. "
|
||||
"Falling back to a very slow implementation.")
|
||||
|
||||
__cache_version__ = "145"
|
||||
__cache_version__ = "144"
|
||||
|
||||
def getCacheFile(path, filename, data_hash):
|
||||
return os.path.join(path, filename + "." + data_hash)
|
||||
@@ -130,9 +130,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
self.broken = self.getvar('BROKEN', metadata)
|
||||
self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata)
|
||||
self.stamp = self.getvar('STAMP', metadata)
|
||||
self.stampclean = self.getvar('STAMPCLEAN', metadata)
|
||||
self.stamp_base = self.flaglist('stamp-base', self.tasks, metadata)
|
||||
self.stamp_base_clean = self.flaglist('stamp-base-clean', 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)
|
||||
@@ -159,9 +157,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.pkg_dp = {}
|
||||
|
||||
cachedata.stamp = {}
|
||||
cachedata.stampclean = {}
|
||||
cachedata.stamp_base = {}
|
||||
cachedata.stamp_base_clean = {}
|
||||
cachedata.stamp_extrainfo = {}
|
||||
cachedata.file_checksums = {}
|
||||
cachedata.fn_provides = {}
|
||||
@@ -193,9 +189,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
|
||||
cachedata.pkg_pepvpr[fn] = (self.pe, self.pv, self.pr)
|
||||
cachedata.pkg_dp[fn] = self.defaultpref
|
||||
cachedata.stamp[fn] = self.stamp
|
||||
cachedata.stampclean[fn] = self.stampclean
|
||||
cachedata.stamp_base[fn] = self.stamp_base
|
||||
cachedata.stamp_base_clean[fn] = self.stamp_base_clean
|
||||
cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo
|
||||
cachedata.file_checksums[fn] = self.file_checksums
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ def check_indent(codestr):
|
||||
|
||||
class CodeParserCache(MultiProcessCache):
|
||||
cache_file_name = "bb_codeparser.dat"
|
||||
CACHE_VERSION = 3
|
||||
CACHE_VERSION = 2
|
||||
|
||||
def __init__(self):
|
||||
MultiProcessCache.__init__(self)
|
||||
@@ -100,8 +100,7 @@ class BufferedLogger(Logger):
|
||||
self.buffer = []
|
||||
|
||||
class PythonParser():
|
||||
getvars = ("d.getVar", "bb.data.getVar", "data.getVar", "d.appendVar", "d.prependVar")
|
||||
containsfuncs = ("bb.utils.contains", "base_contains", "oe.utils.contains")
|
||||
getvars = ("d.getVar", "bb.data.getVar", "data.getVar")
|
||||
execfuncs = ("bb.build.exec_func", "bb.build.exec_task")
|
||||
|
||||
def warn(self, func, arg):
|
||||
@@ -120,7 +119,7 @@ class PythonParser():
|
||||
|
||||
def visit_Call(self, node):
|
||||
name = self.called_node_name(node.func)
|
||||
if name in self.getvars or name in self.containsfuncs:
|
||||
if name in self.getvars:
|
||||
if isinstance(node.args[0], ast.Str):
|
||||
self.var_references.add(node.args[0].s)
|
||||
else:
|
||||
|
||||
@@ -44,9 +44,6 @@ class CommandFailed(CommandExit):
|
||||
self.error = message
|
||||
CommandExit.__init__(self, 1)
|
||||
|
||||
class CommandError(Exception):
|
||||
pass
|
||||
|
||||
class Command:
|
||||
"""
|
||||
A queue of asynchronous commands for bitbake
|
||||
@@ -60,25 +57,21 @@ class Command:
|
||||
self.currentAsyncCommand = None
|
||||
|
||||
def runCommand(self, commandline):
|
||||
command = commandline.pop(0)
|
||||
if hasattr(CommandsSync, command):
|
||||
# Can run synchronous commands straight away
|
||||
command_method = getattr(self.cmds_sync, command)
|
||||
try:
|
||||
result = command_method(self, commandline)
|
||||
except CommandError as exc:
|
||||
return None, exc.args[0]
|
||||
except Exception:
|
||||
return None, traceback.format_exc()
|
||||
else:
|
||||
return result, None
|
||||
if self.currentAsyncCommand is not None:
|
||||
return None, "Busy (%s in progress)" % self.currentAsyncCommand[0]
|
||||
if command not in CommandsAsync.__dict__:
|
||||
return None, "No such command"
|
||||
self.currentAsyncCommand = (command, commandline)
|
||||
self.cooker.server_registration_cb(self.cooker.runCommands, self.cooker)
|
||||
return True, None
|
||||
try:
|
||||
command = commandline.pop(0)
|
||||
if command in CommandsSync.__dict__:
|
||||
# Can run synchronous commands straight away
|
||||
return getattr(CommandsSync, command)(self.cmds_sync, self, commandline)
|
||||
if self.currentAsyncCommand is not None:
|
||||
return "Busy (%s in progress)" % self.currentAsyncCommand[0]
|
||||
if command not in CommandsAsync.__dict__:
|
||||
return "No such command"
|
||||
self.currentAsyncCommand = (command, commandline)
|
||||
self.cooker.server_registration_cb(self.cooker.runCommands, self.cooker)
|
||||
return True
|
||||
except:
|
||||
import traceback
|
||||
return traceback.format_exc()
|
||||
|
||||
def runAsyncCommand(self):
|
||||
try:
|
||||
@@ -146,11 +139,7 @@ class CommandsSync:
|
||||
"""
|
||||
Get any command parsed from the commandline
|
||||
"""
|
||||
cmd_action = command.cooker.commandlineAction
|
||||
if cmd_action['msg']:
|
||||
raise CommandError(msg)
|
||||
else:
|
||||
return cmd_action['action']
|
||||
return command.cooker.commandlineAction
|
||||
|
||||
def getVariable(self, command, params):
|
||||
"""
|
||||
@@ -168,7 +157,7 @@ class CommandsSync:
|
||||
Set the value of variable in configuration.data
|
||||
"""
|
||||
varname = params[0]
|
||||
value = str(params[1])
|
||||
value = params[1]
|
||||
command.cooker.configuration.data.setVar(varname, value)
|
||||
|
||||
def initCooker(self, command, params):
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
"""Code pulled from future python versions, here for compatibility"""
|
||||
|
||||
from collections import MutableMapping, KeysView, ValuesView, ItemsView
|
||||
try:
|
||||
from thread import get_ident as _get_ident
|
||||
except ImportError:
|
||||
from dummy_thread import get_ident as _get_ident
|
||||
|
||||
def total_ordering(cls):
|
||||
"""Class decorator that fills in missing ordering methods"""
|
||||
convert = {
|
||||
@@ -32,210 +26,3 @@ def total_ordering(cls):
|
||||
opfunc.__doc__ = getattr(int, opname).__doc__
|
||||
setattr(cls, opname, opfunc)
|
||||
return cls
|
||||
|
||||
class OrderedDict(dict):
|
||||
'Dictionary that remembers insertion order'
|
||||
# An inherited dict maps keys to values.
|
||||
# The inherited dict provides __getitem__, __len__, __contains__, and get.
|
||||
# The remaining methods are order-aware.
|
||||
# Big-O running times for all methods are the same as regular dictionaries.
|
||||
|
||||
# The internal self.__map dict maps keys to links in a doubly linked list.
|
||||
# The circular doubly linked list starts and ends with a sentinel element.
|
||||
# The sentinel element never gets deleted (this simplifies the algorithm).
|
||||
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
'''Initialize an ordered dictionary. The signature is the same as
|
||||
regular dictionaries, but keyword arguments are not recommended because
|
||||
their insertion order is arbitrary.
|
||||
|
||||
'''
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__root
|
||||
except AttributeError:
|
||||
self.__root = root = [] # sentinel node
|
||||
root[:] = [root, root, None]
|
||||
self.__map = {}
|
||||
self.__update(*args, **kwds)
|
||||
|
||||
def __setitem__(self, key, value, PREV=0, NEXT=1, dict_setitem=dict.__setitem__):
|
||||
'od.__setitem__(i, y) <==> od[i]=y'
|
||||
# Setting a new item creates a new link at the end of the linked list,
|
||||
# and the inherited dictionary is updated with the new key/value pair.
|
||||
if key not in self:
|
||||
root = self.__root
|
||||
last = root[PREV]
|
||||
last[NEXT] = root[PREV] = self.__map[key] = [last, root, key]
|
||||
dict_setitem(self, key, value)
|
||||
|
||||
def __delitem__(self, key, PREV=0, NEXT=1, dict_delitem=dict.__delitem__):
|
||||
'od.__delitem__(y) <==> del od[y]'
|
||||
# Deleting an existing item uses self.__map to find the link which gets
|
||||
# removed by updating the links in the predecessor and successor nodes.
|
||||
dict_delitem(self, key)
|
||||
link_prev, link_next, key = self.__map.pop(key)
|
||||
link_prev[NEXT] = link_next
|
||||
link_next[PREV] = link_prev
|
||||
|
||||
def __iter__(self):
|
||||
'od.__iter__() <==> iter(od)'
|
||||
# Traverse the linked list in order.
|
||||
NEXT, KEY = 1, 2
|
||||
root = self.__root
|
||||
curr = root[NEXT]
|
||||
while curr is not root:
|
||||
yield curr[KEY]
|
||||
curr = curr[NEXT]
|
||||
|
||||
def __reversed__(self):
|
||||
'od.__reversed__() <==> reversed(od)'
|
||||
# Traverse the linked list in reverse order.
|
||||
PREV, KEY = 0, 2
|
||||
root = self.__root
|
||||
curr = root[PREV]
|
||||
while curr is not root:
|
||||
yield curr[KEY]
|
||||
curr = curr[PREV]
|
||||
|
||||
def clear(self):
|
||||
'od.clear() -> None. Remove all items from od.'
|
||||
for node in self.__map.itervalues():
|
||||
del node[:]
|
||||
root = self.__root
|
||||
root[:] = [root, root, None]
|
||||
self.__map.clear()
|
||||
dict.clear(self)
|
||||
|
||||
# -- the following methods do not depend on the internal structure --
|
||||
|
||||
def keys(self):
|
||||
'od.keys() -> list of keys in od'
|
||||
return list(self)
|
||||
|
||||
def values(self):
|
||||
'od.values() -> list of values in od'
|
||||
return [self[key] for key in self]
|
||||
|
||||
def items(self):
|
||||
'od.items() -> list of (key, value) pairs in od'
|
||||
return [(key, self[key]) for key in self]
|
||||
|
||||
def iterkeys(self):
|
||||
'od.iterkeys() -> an iterator over the keys in od'
|
||||
return iter(self)
|
||||
|
||||
def itervalues(self):
|
||||
'od.itervalues -> an iterator over the values in od'
|
||||
for k in self:
|
||||
yield self[k]
|
||||
|
||||
def iteritems(self):
|
||||
'od.iteritems -> an iterator over the (key, value) pairs in od'
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
|
||||
update = MutableMapping.update
|
||||
|
||||
__update = update # let subclasses override update without breaking __init__
|
||||
|
||||
__marker = object()
|
||||
|
||||
def pop(self, key, default=__marker):
|
||||
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding
|
||||
value. If key is not found, d is returned if given, otherwise KeyError
|
||||
is raised.
|
||||
|
||||
'''
|
||||
if key in self:
|
||||
result = self[key]
|
||||
del self[key]
|
||||
return result
|
||||
if default is self.__marker:
|
||||
raise KeyError(key)
|
||||
return default
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
||||
if key in self:
|
||||
return self[key]
|
||||
self[key] = default
|
||||
return default
|
||||
|
||||
def popitem(self, last=True):
|
||||
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
|
||||
Pairs are returned in LIFO order if last is true or FIFO order if false.
|
||||
|
||||
'''
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
key = next(reversed(self) if last else iter(self))
|
||||
value = self.pop(key)
|
||||
return key, value
|
||||
|
||||
def __repr__(self, _repr_running={}):
|
||||
'od.__repr__() <==> repr(od)'
|
||||
call_key = id(self), _get_ident()
|
||||
if call_key in _repr_running:
|
||||
return '...'
|
||||
_repr_running[call_key] = 1
|
||||
try:
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
finally:
|
||||
del _repr_running[call_key]
|
||||
|
||||
def __reduce__(self):
|
||||
'Return state information for pickling'
|
||||
items = [[k, self[k]] for k in self]
|
||||
inst_dict = vars(self).copy()
|
||||
for k in vars(OrderedDict()):
|
||||
inst_dict.pop(k, None)
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def copy(self):
|
||||
'od.copy() -> a shallow copy of od'
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S.
|
||||
If not specified, the value defaults to None.
|
||||
|
||||
'''
|
||||
self = cls()
|
||||
for key in iterable:
|
||||
self[key] = value
|
||||
return self
|
||||
|
||||
def __eq__(self, other):
|
||||
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
||||
while comparison to a regular mapping is order-insensitive.
|
||||
|
||||
'''
|
||||
if isinstance(other, OrderedDict):
|
||||
return len(self)==len(other) and self.items() == other.items()
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
'od.__ne__(y) <==> od!=y'
|
||||
return not self == other
|
||||
|
||||
# -- the following methods support python 3.x style dictionary views --
|
||||
|
||||
def viewkeys(self):
|
||||
"od.viewkeys() -> a set-like object providing a view on od's keys"
|
||||
return KeysView(self)
|
||||
|
||||
def viewvalues(self):
|
||||
"od.viewvalues() -> an object providing a view on od's values"
|
||||
return ValuesView(self)
|
||||
|
||||
def viewitems(self):
|
||||
"od.viewitems() -> a set-like object providing a view on od's items"
|
||||
return ItemsView(self)
|
||||
|
||||
@@ -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()
|
||||
@@ -219,12 +218,6 @@ class BBCooker:
|
||||
nice = int(nice) - curnice
|
||||
buildlog.verbose("Renice to %s " % os.nice(nice))
|
||||
|
||||
if self.status:
|
||||
del self.status
|
||||
self.status = bb.cache.CacheData(self.caches_array)
|
||||
|
||||
self.handleCollections( self.configuration.data.getVar("BBFILE_COLLECTIONS", True) )
|
||||
|
||||
def parseCommandLine(self):
|
||||
# Parse any commandline into actions
|
||||
self.commandlineAction = {'action':None, 'msg':None}
|
||||
@@ -278,8 +271,8 @@ class BBCooker:
|
||||
pkg_pn = self.status.pkg_pn
|
||||
(latest_versions, preferred_versions) = bb.providers.findProviders(self.configuration.data, self.status, pkg_pn)
|
||||
|
||||
logger.plain("%-35s %25s %25s", "Recipe Name", "Latest Version", "Preferred Version")
|
||||
logger.plain("%-35s %25s %25s\n", "===========", "==============", "=================")
|
||||
logger.plain("%-35s %25s %25s", "Package Name", "Latest Version", "Preferred Version")
|
||||
logger.plain("%-35s %25s %25s\n", "============", "==============", "=================")
|
||||
|
||||
for p in sorted(pkg_pn):
|
||||
pref = preferred_versions[p]
|
||||
@@ -304,6 +297,8 @@ class BBCooker:
|
||||
# Parse the configuration here. We need to do it explicitly here since
|
||||
# this showEnvironment() code path doesn't use the cache
|
||||
self.parseConfiguration()
|
||||
self.status = bb.cache.CacheData(self.caches_array)
|
||||
self.handleCollections( self.configuration.data.getVar("BBFILE_COLLECTIONS", True) )
|
||||
|
||||
fn, cls = bb.cache.Cache.virtualfn2realfn(buildfile)
|
||||
fn = self.matchFile(fn)
|
||||
@@ -642,8 +637,7 @@ class BBCooker:
|
||||
# Calculate priorities for each file
|
||||
matched = set()
|
||||
for p in self.status.pkg_fn:
|
||||
realfn, cls = bb.cache.Cache.virtualfn2realfn(p)
|
||||
self.status.bbfile_priority[p] = self.calc_bbfile_priority(realfn, matched)
|
||||
self.status.bbfile_priority[p] = self.calc_bbfile_priority(p, matched)
|
||||
|
||||
# Don't show the warning if the BBFILE_PATTERN did match .bbappend files
|
||||
unmatched = set()
|
||||
@@ -939,13 +933,13 @@ class BBCooker:
|
||||
errors = True
|
||||
continue
|
||||
if lver <> depver:
|
||||
parselog.error("Layer '%s' depends on version %d of layer '%s', but version %d is enabled in your configuration", c, depver, dep, lver)
|
||||
parselog.error("Layer dependency %s of layer %s is at version %d, expected %d", dep, c, lver, depver)
|
||||
errors = True
|
||||
else:
|
||||
parselog.error("Layer '%s' depends on version %d of layer '%s', which exists in your configuration but does not specify a version", c, depver, dep)
|
||||
parselog.error("Layer dependency %s of layer %s has no version, expected %d", dep, c, depver)
|
||||
errors = True
|
||||
else:
|
||||
parselog.error("Layer '%s' depends on layer '%s', but this layer is not enabled in your configuration", c, dep)
|
||||
parselog.error("Layer dependency %s of layer %s not found", dep, c)
|
||||
errors = True
|
||||
collection_depends[c] = depnamelist
|
||||
else:
|
||||
@@ -1040,6 +1034,8 @@ class BBCooker:
|
||||
# Parse the configuration here. We need to do it explicitly here since
|
||||
# buildFile() doesn't use the cache
|
||||
self.parseConfiguration()
|
||||
self.status = bb.cache.CacheData(self.caches_array)
|
||||
self.handleCollections( self.configuration.data.getVar("BBFILE_COLLECTIONS", True) )
|
||||
|
||||
# If we are told to do the None task then query the default task
|
||||
if (task == None):
|
||||
@@ -1061,10 +1057,6 @@ class BBCooker:
|
||||
info_array = infos[fn]
|
||||
except KeyError:
|
||||
bb.fatal("%s does not exist" % fn)
|
||||
|
||||
if info_array[0].skipped:
|
||||
bb.fatal("%s was skipped: %s" % (fn, info_array[0].skipreason))
|
||||
|
||||
self.status.add_from_recipeinfo(fn, info_array)
|
||||
|
||||
# Tweak some variables
|
||||
@@ -1193,12 +1185,18 @@ class BBCooker:
|
||||
if self.state != state.parsing:
|
||||
self.parseConfiguration ()
|
||||
|
||||
if self.status:
|
||||
del self.status
|
||||
self.status = bb.cache.CacheData(self.caches_array)
|
||||
|
||||
ignore = self.configuration.data.getVar("ASSUME_PROVIDED", True) or ""
|
||||
self.status.ignored_dependencies = set(ignore.split())
|
||||
|
||||
for dep in self.configuration.extra_assume_provided:
|
||||
self.status.ignored_dependencies.add(dep)
|
||||
|
||||
self.handleCollections( self.configuration.data.getVar("BBFILE_COLLECTIONS", True) )
|
||||
|
||||
(filelist, masked) = self.collect_bbfiles()
|
||||
self.configuration.data.renameVar("__depends", "__base_depends")
|
||||
|
||||
@@ -1207,8 +1205,6 @@ class BBCooker:
|
||||
|
||||
if not self.parser.parse_next():
|
||||
collectlog.debug(1, "parsing complete")
|
||||
if self.parser.error:
|
||||
sys.exit(1)
|
||||
self.show_appends_with_no_recipes()
|
||||
self.buildDepgraph()
|
||||
self.state = state.running
|
||||
@@ -1353,10 +1349,7 @@ class BBCooker:
|
||||
# Empty the environment. The environment will be populated as
|
||||
# necessary from the data store.
|
||||
#bb.utils.empty_environment()
|
||||
try:
|
||||
prserv.serv.auto_start(self.configuration.data)
|
||||
except prserv.serv.PRServiceConfigError:
|
||||
bb.event.fire(CookerExit(), self.configuration.event_data)
|
||||
prserv.serv.auto_start(self.configuration.data)
|
||||
return
|
||||
|
||||
def post_serve(self):
|
||||
@@ -1608,7 +1601,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:
|
||||
@@ -1665,45 +1657,25 @@ class CookerParser(object):
|
||||
except StopIteration:
|
||||
self.shutdown()
|
||||
return False
|
||||
except bb.BBHandledException as exc:
|
||||
self.error += 1
|
||||
logger.error('Failed to parse recipe: %s' % exc.recipe)
|
||||
self.shutdown(clean=False)
|
||||
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)
|
||||
return False
|
||||
except bb.parse.ParseError as exc:
|
||||
self.error += 1
|
||||
logger.error(str(exc))
|
||||
self.shutdown(clean=False)
|
||||
return 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)
|
||||
return False
|
||||
except SyntaxError as exc:
|
||||
self.error += 1
|
||||
logger.error('Unable to parse %s', exc.recipe)
|
||||
self.shutdown(clean=False)
|
||||
return False
|
||||
except Exception as exc:
|
||||
self.error += 1
|
||||
etype, value, tb = sys.exc_info()
|
||||
if hasattr(value, "recipe"):
|
||||
logger.error('Unable to parse %s', value.recipe,
|
||||
exc_info=(etype, value, exc.traceback))
|
||||
else:
|
||||
# Most likely, an exception occurred during raising an exception
|
||||
import traceback
|
||||
logger.error('Exception during parse: %s' % traceback.format_exc())
|
||||
logger.error('Unable to parse %s', value.recipe,
|
||||
exc_info=(etype, value, exc.traceback))
|
||||
self.shutdown(clean=False)
|
||||
return False
|
||||
|
||||
self.current += 1
|
||||
self.virtuals += len(result)
|
||||
|
||||
@@ -291,8 +291,6 @@ def build_dependencies(key, keys, shelldeps, vardepvals, d):
|
||||
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:
|
||||
@@ -323,8 +321,9 @@ def build_dependencies(key, keys, shelldeps, vardepvals, d):
|
||||
|
||||
deps |= set((vardeps or "").split())
|
||||
deps -= set((d.getVarFlag(key, "vardepsexclude", True) or "").split())
|
||||
except Exception as e:
|
||||
raise bb.data_smart.ExpansionError(key, None, e)
|
||||
except:
|
||||
bb.note("Error expanding variable %s" % key)
|
||||
raise
|
||||
return deps, value
|
||||
#bb.note("Variable %s references %s and calls %s" % (key, str(deps), str(execs)))
|
||||
#d.setVarFlag(key, "vardeps", deps)
|
||||
|
||||
@@ -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"\${@.+?}")
|
||||
|
||||
@@ -103,10 +103,7 @@ class ExpansionError(Exception):
|
||||
self.variablename = varname
|
||||
self.exception = exception
|
||||
if varname:
|
||||
if expression:
|
||||
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 variable %s: %s: %s" % (varname, type(exception).__name__, exception)
|
||||
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)
|
||||
Exception.__init__(self, self.msg)
|
||||
@@ -283,10 +280,10 @@ class DataSmart(MutableMapping):
|
||||
self._seen_overrides[override].add( var )
|
||||
|
||||
# setting var
|
||||
self.dict[var]["_content"] = value
|
||||
self.dict[var]["content"] = value
|
||||
|
||||
def getVar(self, var, expand=False, noweakdefault=False):
|
||||
value = self.getVarFlag(var, "_content", False, noweakdefault)
|
||||
value = self.getVarFlag(var, "content", False, noweakdefault)
|
||||
|
||||
# Call expand() separately to make use of the expand cache
|
||||
if expand and value:
|
||||
@@ -343,7 +340,7 @@ class DataSmart(MutableMapping):
|
||||
if local_var:
|
||||
if flag in local_var:
|
||||
value = copy.copy(local_var[flag])
|
||||
elif flag == "_content" and "defaultval" in local_var and not noweakdefault:
|
||||
elif flag == "content" and "defaultval" in local_var and not noweakdefault:
|
||||
value = copy.copy(local_var["defaultval"])
|
||||
if expand and value:
|
||||
value = self.expand(value, None)
|
||||
@@ -372,7 +369,7 @@ class DataSmart(MutableMapping):
|
||||
self._makeShadowCopy(var)
|
||||
|
||||
for i in flags:
|
||||
if i == "_content":
|
||||
if i == "content":
|
||||
continue
|
||||
self.dict[var][i] = flags[i]
|
||||
|
||||
@@ -382,7 +379,7 @@ class DataSmart(MutableMapping):
|
||||
|
||||
if local_var:
|
||||
for i in local_var:
|
||||
if i.startswith("_"):
|
||||
if i == "content":
|
||||
continue
|
||||
flags[i] = local_var[i]
|
||||
|
||||
@@ -399,10 +396,10 @@ class DataSmart(MutableMapping):
|
||||
content = None
|
||||
|
||||
# try to save the content
|
||||
if "_content" in self.dict[var]:
|
||||
content = self.dict[var]["_content"]
|
||||
if "content" in self.dict[var]:
|
||||
content = self.dict[var]["content"]
|
||||
self.dict[var] = {}
|
||||
self.dict[var]["_content"] = content
|
||||
self.dict[var]["content"] = content
|
||||
else:
|
||||
del self.dict[var]
|
||||
|
||||
@@ -474,16 +471,12 @@ class DataSmart(MutableMapping):
|
||||
|
||||
def get_hash(self):
|
||||
data = {}
|
||||
d = self.createCopy()
|
||||
bb.data.expandKeys(d)
|
||||
bb.data.update_data(d)
|
||||
|
||||
config_whitelist = set((d.getVar("BB_HASHCONFIG_WHITELIST", True) or "").split())
|
||||
keys = set(key for key in iter(d) if not key.startswith("__"))
|
||||
config_whitelist = set((self.getVar("BB_HASHCONFIG_WHITELIST", True) or "").split())
|
||||
keys = set(key for key in iter(self) if not key.startswith("__"))
|
||||
for key in keys:
|
||||
if key in config_whitelist:
|
||||
continue
|
||||
value = d.getVar(key, False) or ""
|
||||
value = self.getVar(key, False) or ""
|
||||
data.update({key:value})
|
||||
|
||||
data_str = str([(k, data[k]) for k in sorted(data.keys())])
|
||||
|
||||
@@ -32,7 +32,6 @@ import logging
|
||||
import atexit
|
||||
import traceback
|
||||
import bb.utils
|
||||
import bb.compat
|
||||
|
||||
# This is the pid for which we should generate the event. This is set when
|
||||
# the runqueue forks off.
|
||||
@@ -54,7 +53,7 @@ Registered = 10
|
||||
AlreadyRegistered = 14
|
||||
|
||||
# Internal
|
||||
_handlers = bb.compat.OrderedDict()
|
||||
_handlers = {}
|
||||
_ui_handlers = {}
|
||||
_ui_handler_seq = 0
|
||||
|
||||
@@ -105,18 +104,6 @@ def print_ui_queue():
|
||||
console = logging.StreamHandler(sys.stdout)
|
||||
console.setFormatter(BBLogFormatter("%(levelname)s: %(message)s"))
|
||||
logger.handlers = [console]
|
||||
|
||||
# First check to see if we have any proper messages
|
||||
msgprint = False
|
||||
for event in ui_queue:
|
||||
if isinstance(event, logging.LogRecord):
|
||||
if event.levelno > logging.DEBUG:
|
||||
logger.handle(event)
|
||||
msgprint = True
|
||||
if msgprint:
|
||||
return
|
||||
|
||||
# Nope, so just print all of the messages we have (including debug messages)
|
||||
for event in ui_queue:
|
||||
if isinstance(event, logging.LogRecord):
|
||||
logger.handle(event)
|
||||
@@ -188,7 +175,7 @@ def register(name, handler):
|
||||
_handlers[name] = noop
|
||||
return
|
||||
env = {}
|
||||
bb.utils.better_exec(code, env)
|
||||
bb.utils.simple_exec(code, env)
|
||||
func = bb.utils.better_eval(name, env)
|
||||
_handlers[name] = func
|
||||
else:
|
||||
@@ -325,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"""
|
||||
@@ -510,15 +489,6 @@ class MsgFatal(MsgBase):
|
||||
class MsgPlain(MsgBase):
|
||||
"""General output"""
|
||||
|
||||
class LogExecTTY(Event):
|
||||
"""Send event containing program to spawn on tty of the logger"""
|
||||
def __init__(self, msg, prog, sleep_delay, retries):
|
||||
Event.__init__(self)
|
||||
self.msg = msg
|
||||
self.prog = prog
|
||||
self.sleep_delay = sleep_delay
|
||||
self.retries = retries
|
||||
|
||||
class LogHandler(logging.Handler):
|
||||
"""Dispatch logging messages as bitbake events"""
|
||||
|
||||
@@ -562,7 +532,6 @@ class SanityCheckFailed(Event):
|
||||
"""
|
||||
Event to indicate sanity check has failed
|
||||
"""
|
||||
def __init__(self, msg, network_error=False):
|
||||
def __init__(self, msg):
|
||||
Event.__init__(self)
|
||||
self._msg = msg
|
||||
self._network_error = network_error
|
||||
|
||||
@@ -54,7 +54,7 @@ class MalformedUrl(BBFetchException):
|
||||
msg = "The URL: '%s' is invalid and cannot be interpreted" % url
|
||||
self.url = url
|
||||
BBFetchException.__init__(self, msg)
|
||||
self.args = (url,)
|
||||
self.args = url
|
||||
|
||||
class FetchError(BBFetchException):
|
||||
"""General fetcher exception when something happens incorrectly"""
|
||||
@@ -70,9 +70,6 @@ class FetchError(BBFetchException):
|
||||
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):
|
||||
@@ -87,7 +84,7 @@ class NoMethodError(BBFetchException):
|
||||
msg = "Could not find a fetcher which supports the URL: '%s'" % url
|
||||
self.url = url
|
||||
BBFetchException.__init__(self, msg)
|
||||
self.args = (url,)
|
||||
self.args = url
|
||||
|
||||
class MissingParameterError(BBFetchException):
|
||||
"""Exception raised when a fetch method is missing a critical parameter in the url"""
|
||||
@@ -178,9 +175,6 @@ def encodeurl(decoded):
|
||||
url += "@"
|
||||
if host and type != "file":
|
||||
url += "%s" % host
|
||||
# Standardise path to ensure comparisons work
|
||||
while '//' in path:
|
||||
path = path.replace("//", "/")
|
||||
url += "%s" % urllib.quote(path)
|
||||
if p:
|
||||
for parm in p:
|
||||
@@ -320,7 +314,7 @@ def verify_checksum(u, ud, d):
|
||||
# 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'
|
||||
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)
|
||||
@@ -348,17 +342,11 @@ 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 + '\nIf this change is expected (e.g. you have upgraded to a new version without updating the checksums) then you can use these lines within the recipe:\nSRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"\nOtherwise you should retry the download and/or check with upstream to determine if the file has become corrupted or otherwise unexpectedly modified.\n' % (ud.md5_name, md5data, ud.sha256_name, sha256data)
|
||||
|
||||
if len(msg):
|
||||
raise ChecksumError('Checksum mismatch!%s' % msg, u)
|
||||
@@ -471,13 +459,7 @@ def runfetchcmd(cmd, d, quiet = False, cleanup = []):
|
||||
except bb.process.NotFoundError as e:
|
||||
error_message = "Fetch command %s" % (e.command)
|
||||
except bb.process.ExecutionError as e:
|
||||
if e.stdout:
|
||||
output = "output:\n%s\n%s" % (e.stdout, e.stderr)
|
||||
elif e.stderr:
|
||||
output = "output:\n%s" % e.stderr
|
||||
else:
|
||||
output = "no output"
|
||||
error_message = "Fetch command failed with exit code %s, %s" % (e.exitcode, output)
|
||||
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)
|
||||
if not success:
|
||||
@@ -575,11 +557,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
|
||||
|
||||
@@ -590,8 +568,6 @@ def try_mirror_url(newuri, origud, ud, ld, check = False):
|
||||
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))
|
||||
@@ -947,16 +923,14 @@ class FetchMethod(object):
|
||||
if dos:
|
||||
cmd = '%s -a' % cmd
|
||||
cmd = "%s '%s'" % (cmd, file)
|
||||
elif file.endswith('.rpm') or file.endswith('.srpm'):
|
||||
elif file.endswith('.src.rpm') or file.endswith('.srpm'):
|
||||
if 'extract' in urldata.parm:
|
||||
unpack_file = urldata.parm.get('extract')
|
||||
cmd = 'rpm2cpio.sh %s | cpio -id %s' % (file, unpack_file)
|
||||
cmd = 'rpm2cpio.sh %s | cpio -i %s' % (file, unpack_file)
|
||||
iterate = True
|
||||
iterate_file = unpack_file
|
||||
else:
|
||||
cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
|
||||
elif file.endswith('.deb') or file.endswith('.ipk'):
|
||||
cmd = 'ar -p %s data.tar.gz | zcat | tar --no-same-owner -xpf -' % file
|
||||
cmd = 'rpm2cpio.sh %s | cpio -i' % (file)
|
||||
|
||||
if not unpack or not cmd:
|
||||
# If file == dest, then avoid any copies, as we already put the file into dest!
|
||||
@@ -1204,10 +1178,7 @@ class Fetch(object):
|
||||
|
||||
except BBFetchException as e:
|
||||
if isinstance(e, ChecksumError):
|
||||
logger.warn("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
|
||||
logger.debug(1, str(e))
|
||||
elif isinstance(e, NoChecksumError):
|
||||
raise
|
||||
logger.warn("Checksum error encountered with download (will attempt other sources): %s" % str(e))
|
||||
else:
|
||||
logger.warn('Failed to fetch URL %s, attempting MIRRORS if available' % u)
|
||||
logger.debug(1, str(e))
|
||||
@@ -1225,13 +1196,6 @@ class Fetch(object):
|
||||
|
||||
update_stamp(u, ud, self.d)
|
||||
|
||||
except BBFetchException as e:
|
||||
if isinstance(e, NoChecksumError):
|
||||
logger.error("%s" % str(e))
|
||||
elif isinstance(e, ChecksumError):
|
||||
logger.error("Checksum failure fetching %s" % u)
|
||||
raise
|
||||
|
||||
finally:
|
||||
bb.utils.unlockfile(lf)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -29,6 +29,7 @@ BitBake build tools.
|
||||
import os
|
||||
import logging
|
||||
import bb
|
||||
from bb import data
|
||||
from bb.fetch2 import FetchMethod, FetchError, MissingParameterError, logger
|
||||
from bb.fetch2 import runfetchcmd
|
||||
|
||||
@@ -63,7 +64,7 @@ class Cvs(FetchMethod):
|
||||
if 'fullpath' in ud.parm:
|
||||
fullpath = '_fullpath'
|
||||
|
||||
ud.localfile = bb.data.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath), d)
|
||||
ud.localfile = data.expand('%s_%s_%s_%s%s%s.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.tag, ud.date, norecurse, fullpath), d)
|
||||
|
||||
def need_update(self, url, ud, d):
|
||||
if (ud.date == "now"):
|
||||
@@ -87,10 +88,10 @@ class Cvs(FetchMethod):
|
||||
cvsroot = ud.path
|
||||
else:
|
||||
cvsroot = ":" + method
|
||||
cvsproxyhost = d.getVar('CVS_PROXY_HOST', True)
|
||||
cvsproxyhost = data.getVar('CVS_PROXY_HOST', d, True)
|
||||
if cvsproxyhost:
|
||||
cvsroot += ";proxy=" + cvsproxyhost
|
||||
cvsproxyport = d.getVar('CVS_PROXY_PORT', True)
|
||||
cvsproxyport = data.getVar('CVS_PROXY_PORT', d, True)
|
||||
if cvsproxyport:
|
||||
cvsroot += ";proxyport=" + cvsproxyport
|
||||
cvsroot += ":" + ud.user
|
||||
@@ -111,8 +112,8 @@ class Cvs(FetchMethod):
|
||||
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)
|
||||
cvscmd = cvsbasecmd + "'-d" + cvsroot + "' co " + " ".join(options) + " " + ud.module
|
||||
cvsupdatecmd = cvsbasecmd + "'-d" + cvsroot + "' update -d -P " + " ".join(options)
|
||||
|
||||
if cvs_rsh:
|
||||
cvscmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvscmd)
|
||||
@@ -120,8 +121,8 @@ class Cvs(FetchMethod):
|
||||
|
||||
# create module directory
|
||||
logger.debug(2, "Fetch: checking for module directory")
|
||||
pkg = d.getVar('PN', True)
|
||||
pkgdir = os.path.join(d.getVar('CVSDIR', True), pkg)
|
||||
pkg = data.expand('${PN}', d)
|
||||
pkgdir = os.path.join(data.expand('${CVSDIR}', localdata), pkg)
|
||||
moddir = os.path.join(pkgdir, localdir)
|
||||
if os.access(os.path.join(moddir, 'CVS'), os.R_OK):
|
||||
logger.info("Update " + loc)
|
||||
@@ -162,9 +163,12 @@ class Cvs(FetchMethod):
|
||||
|
||||
def clean(self, ud, d):
|
||||
""" Clean CVS Files and tarballs """
|
||||
|
||||
pkg = d.getVar('PN', True)
|
||||
pkgdir = os.path.join(d.getVar("CVSDIR", True), pkg)
|
||||
|
||||
pkg = data.expand('${PN}', d)
|
||||
localdata = data.createCopy(d)
|
||||
data.setVar('OVERRIDES', "cvs:%s" % data.getVar('OVERRIDES', localdata), localdata)
|
||||
data.update_data(localdata)
|
||||
pkgdir = os.path.join(data.expand('${CVSDIR}', localdata), pkg)
|
||||
|
||||
bb.utils.remove(pkgdir, True)
|
||||
bb.utils.remove(ud.localpath)
|
||||
|
||||
@@ -245,23 +245,7 @@ class Git(FetchMethod):
|
||||
if ud.bareclone:
|
||||
cloneflags += " --mirror"
|
||||
|
||||
# Versions of git prior to 1.7.9.2 have issues where foo.git and foo get confused
|
||||
# and you end up with some horrible union of the two when you attempt to clone it
|
||||
# The least invasive workaround seems to be a symlink to the real directory to
|
||||
# fool git into ignoring any .git version that may also be present.
|
||||
#
|
||||
# The issue is fixed in more recent versions of git so we can drop this hack in future
|
||||
# when that version becomes common enough.
|
||||
clonedir = ud.clonedir
|
||||
if not ud.path.endswith(".git"):
|
||||
indirectiondir = destdir[:-1] + ".indirectionsymlink"
|
||||
if os.path.exists(indirectiondir):
|
||||
os.remove(indirectiondir)
|
||||
bb.utils.mkdirhier(os.path.dirname(indirectiondir))
|
||||
os.symlink(ud.clonedir, indirectiondir)
|
||||
clonedir = indirectiondir
|
||||
|
||||
runfetchcmd("git clone %s %s/ %s" % (cloneflags, clonedir, destdir), d)
|
||||
runfetchcmd("git clone %s %s/ %s" % (cloneflags, ud.clonedir, destdir), d)
|
||||
if not ud.nocheckout:
|
||||
os.chdir(destdir)
|
||||
if subdir != "":
|
||||
|
||||
@@ -30,8 +30,7 @@ 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 +41,28 @@ 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(urllib.unquote(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]
|
||||
path = urllib.unquote(path)
|
||||
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 +75,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):
|
||||
"""
|
||||
|
||||
@@ -10,12 +10,6 @@ IETF secsh internet draft:
|
||||
Currently does not support the sftp parameters, as this uses scp
|
||||
Also does not support the 'fingerprint' connection parameter.
|
||||
|
||||
Please note that '/' is used as host, path separator not ':' as you may
|
||||
be used to, also '~' can be used to specify user HOME, but again after '/'
|
||||
|
||||
Example SRC_URI:
|
||||
SRC_URI = "ssh://user@host.example.com/dir/path/file.txt"
|
||||
SRC_URI = "ssh://user@host.example.com/~/file.txt"
|
||||
'''
|
||||
|
||||
# Copyright (C) 2006 OpenedHand Ltd.
|
||||
@@ -78,19 +72,15 @@ class SSH(FetchMethod):
|
||||
def supports_checksum(self, urldata):
|
||||
return False
|
||||
|
||||
def urldata_init(self, urldata, d):
|
||||
if 'protocol' in urldata.parm and urldata.parm['protocol'] == 'git':
|
||||
raise bb.fetch2.ParameterError(
|
||||
"Invalid protocol - if you wish to fetch from a git " +
|
||||
"repository using ssh, you need to use " +
|
||||
"git:// prefix with protocol=ssh", urldata.url)
|
||||
def localpath(self, url, urldata, d):
|
||||
m = __pattern__.match(urldata.url)
|
||||
path = m.group('path')
|
||||
host = m.group('host')
|
||||
urldata.localpath = os.path.join(d.getVar('DL_DIR', True), os.path.basename(path))
|
||||
lpath = os.path.join(data.getVar('DL_DIR', d, True), host, os.path.basename(path))
|
||||
return lpath
|
||||
|
||||
def download(self, url, urldata, d):
|
||||
dldir = d.getVar('DL_DIR', True)
|
||||
dldir = data.getVar('DL_DIR', d, True)
|
||||
|
||||
m = __pattern__.match(url)
|
||||
path = m.group('path')
|
||||
@@ -99,10 +89,16 @@ class SSH(FetchMethod):
|
||||
user = m.group('user')
|
||||
password = m.group('pass')
|
||||
|
||||
ldir = os.path.join(dldir, host)
|
||||
lpath = os.path.join(ldir, os.path.basename(path))
|
||||
|
||||
if not os.path.exists(ldir):
|
||||
os.makedirs(ldir)
|
||||
|
||||
if port:
|
||||
portarg = '-P %s' % port
|
||||
port = '-P %s' % port
|
||||
else:
|
||||
portarg = ''
|
||||
port = ''
|
||||
|
||||
if user:
|
||||
fr = user
|
||||
@@ -116,9 +112,9 @@ class SSH(FetchMethod):
|
||||
|
||||
import commands
|
||||
cmd = 'scp -B -r %s %s %s/' % (
|
||||
portarg,
|
||||
port,
|
||||
commands.mkarg(fr),
|
||||
commands.mkarg(dldir)
|
||||
commands.mkarg(ldir)
|
||||
)
|
||||
|
||||
bb.fetch2.check_network_access(d, cmd, urldata.url)
|
||||
|
||||
@@ -71,7 +71,7 @@ class Svn(FetchMethod):
|
||||
command is "fetch", "update", "info"
|
||||
"""
|
||||
|
||||
proto = ud.parm.get('protocol', 'svn')
|
||||
proto = ud.parm.get('proto', 'svn')
|
||||
|
||||
svn_rsh = None
|
||||
if proto == "svn+ssh" and "rsh" in ud.parm:
|
||||
|
||||
@@ -49,15 +49,8 @@ class Wget(FetchMethod):
|
||||
return True
|
||||
|
||||
def urldata_init(self, ud, d):
|
||||
if 'protocol' in ud.parm:
|
||||
if ud.parm['protocol'] == 'git':
|
||||
raise bb.fetch2.ParameterError("Invalid protocol - if you wish to fetch from a git repository using http, you need to instead use the git:// prefix with protocol=http", ud.url)
|
||||
|
||||
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):
|
||||
@@ -65,14 +58,11 @@ class Wget(FetchMethod):
|
||||
|
||||
basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -t 2 -T 30 -nv --passive-ftp --no-check-certificate"
|
||||
|
||||
if 'downloadfilename' in ud.parm:
|
||||
basecmd += " -O ${DL_DIR}/" + ud.localfile
|
||||
|
||||
if checkonly:
|
||||
fetchcmd = d.getVar("CHECKCOMMAND_wget", True) or d.expand(basecmd + " --spider '${URI}'")
|
||||
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 + " -c -P ${DL_DIR} '${URI}'")
|
||||
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}'")
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@
|
||||
from bb.utils import better_compile, better_exec
|
||||
from bb import error
|
||||
|
||||
# A dict of function names we have seen
|
||||
# A dict of modules we have handled
|
||||
# it is the number of .bbclasses + x in size
|
||||
_parsed_methods = { }
|
||||
_parsed_fns = { }
|
||||
|
||||
def insert_method(modulename, code, fn):
|
||||
@@ -54,18 +56,29 @@ def insert_method(modulename, code, fn):
|
||||
else:
|
||||
_parsed_fns[name] = modulename
|
||||
|
||||
# A dict of modules the parser has finished with
|
||||
_parsed_methods = {}
|
||||
def check_insert_method(modulename, code, fn):
|
||||
"""
|
||||
Add the code if it wasnt added before. The module
|
||||
name will be used for that
|
||||
|
||||
Variables:
|
||||
@modulename a short name e.g. base.bbclass
|
||||
@code The actual python code
|
||||
@fn The filename from the outer file
|
||||
"""
|
||||
if not modulename in _parsed_methods:
|
||||
return insert_method(modulename, code, fn)
|
||||
_parsed_methods[modulename] = 1
|
||||
|
||||
def parsed_module(modulename):
|
||||
"""
|
||||
Has module been parsed?
|
||||
Inform me file xyz was parsed
|
||||
"""
|
||||
return modulename in _parsed_methods
|
||||
|
||||
def set_parsed_module(modulename):
|
||||
"""
|
||||
Set module as parsed
|
||||
"""
|
||||
_parsed_methods[modulename] = True
|
||||
|
||||
def get_parsed_dict():
|
||||
"""
|
||||
shortcut
|
||||
"""
|
||||
return _parsed_methods
|
||||
|
||||
@@ -128,7 +128,7 @@ def getDiskData(BBDirs, configuration):
|
||||
if not os.path.exists(path):
|
||||
bb.utils.mkdirhier(path)
|
||||
mountedDev = getMountedDev(path)
|
||||
devDict[mountedDev] = [action, path, minSpace, minInode]
|
||||
devDict[mountedDev] = action, path, minSpace, minInode
|
||||
|
||||
return devDict
|
||||
|
||||
@@ -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,24 +219,15 @@ 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
|
||||
|
||||
if self.devDict[dev][3] and freeInode < self.devDict[dev][3]:
|
||||
# Some fs formats' (e.g., btrfs) statvfs.f_files (inodes) is
|
||||
# zero, this is a feature of the fs, we disable the inode
|
||||
# checking for such a fs.
|
||||
if st.f_files == 0:
|
||||
logger.warn("Inode check for %s is unavaliable, remove it from disk monitor" % dev)
|
||||
self.devDict[dev][3] = None
|
||||
continue
|
||||
# Always show warning, the self.checked would always be False if the action is WARN
|
||||
if self.preFreeI[dev] == 0 or self.preFreeI[dev] - freeInode > self.inodeInterval and not self.checked[dev]:
|
||||
logger.warn("The free inode of %s is running low (%.3fK left)" % (dev, freeInode / 1024.0))
|
||||
@@ -247,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
|
||||
|
||||
@@ -31,6 +31,7 @@ import itertools
|
||||
from bb import methodpool
|
||||
from bb.parse import logger
|
||||
|
||||
__parsed_methods__ = bb.methodpool.get_parsed_dict()
|
||||
_bbversions_re = re.compile(r"\[(?P<from>[0-9]+)-(?P<to>[0-9]+)\]")
|
||||
|
||||
class StatementGroup(list):
|
||||
@@ -125,25 +126,23 @@ class MethodNode(AstNode):
|
||||
self.body = body
|
||||
|
||||
def eval(self, data):
|
||||
text = '\n'.join(self.body)
|
||||
if self.func_name == "__anonymous":
|
||||
funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(string.maketrans('/.+-', '____'))))
|
||||
if not funcname in bb.methodpool._parsed_fns:
|
||||
text = "def %s(d):\n" % (funcname) + text
|
||||
text = "def %s(d):\n" % (funcname) + '\n'.join(self.body)
|
||||
bb.methodpool.insert_method(funcname, text, self.filename)
|
||||
anonfuncs = data.getVar('__BBANONFUNCS') or []
|
||||
anonfuncs.append(funcname)
|
||||
data.setVar('__BBANONFUNCS', anonfuncs)
|
||||
data.setVar(funcname, text)
|
||||
else:
|
||||
data.setVarFlag(self.func_name, "func", 1)
|
||||
data.setVar(self.func_name, text)
|
||||
data.setVar(self.func_name, '\n'.join(self.body))
|
||||
|
||||
class PythonMethodNode(AstNode):
|
||||
def __init__(self, filename, lineno, function, modulename, body):
|
||||
def __init__(self, filename, lineno, function, define, body):
|
||||
AstNode.__init__(self, filename, lineno)
|
||||
self.function = function
|
||||
self.modulename = modulename
|
||||
self.define = define
|
||||
self.body = body
|
||||
|
||||
def eval(self, data):
|
||||
@@ -151,8 +150,8 @@ class PythonMethodNode(AstNode):
|
||||
# 'this' file. This means we will not parse methods from
|
||||
# bb classes twice
|
||||
text = '\n'.join(self.body)
|
||||
if not bb.methodpool.parsed_module(self.modulename):
|
||||
bb.methodpool.insert_method(self.modulename, text, self.filename)
|
||||
if not bb.methodpool.parsed_module(self.define):
|
||||
bb.methodpool.insert_method(self.define, text, self.filename)
|
||||
data.setVarFlag(self.function, "func", 1)
|
||||
data.setVarFlag(self.function, "python", 1)
|
||||
data.setVar(self.function, text)
|
||||
@@ -213,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):
|
||||
@@ -282,8 +281,8 @@ def handleData(statements, filename, lineno, groupd):
|
||||
def handleMethod(statements, filename, lineno, func_name, body):
|
||||
statements.append(MethodNode(filename, lineno, func_name, body))
|
||||
|
||||
def handlePythonMethod(statements, filename, lineno, funcname, modulename, body):
|
||||
statements.append(PythonMethodNode(filename, lineno, funcname, modulename, body))
|
||||
def handlePythonMethod(statements, filename, lineno, funcname, root, body):
|
||||
statements.append(PythonMethodNode(filename, lineno, funcname, root, body))
|
||||
|
||||
def handleMethodFlags(statements, filename, lineno, key, m):
|
||||
statements.append(MethodFlagsNode(filename, lineno, key, m))
|
||||
@@ -321,7 +320,7 @@ def finalize(fn, d, variant = None):
|
||||
code = []
|
||||
for funcname in d.getVar("__BBANONFUNCS") or []:
|
||||
code.append("%s(d)" % funcname)
|
||||
bb.utils.better_exec("\n".join(code), {"d": d})
|
||||
bb.utils.simple_exec("\n".join(code), {"d": d})
|
||||
bb.data.update_data(d)
|
||||
|
||||
tasklist = d.getVar('__BBTASKS') or []
|
||||
|
||||
@@ -161,7 +161,7 @@ def handle(fn, d, include):
|
||||
|
||||
# we have parsed the bb class now
|
||||
if ext == ".bbclass" or ext == ".inc":
|
||||
bb.methodpool.set_parsed_module(base_name)
|
||||
bb.methodpool.get_parsed_dict()[base_name] = 1
|
||||
|
||||
return d
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import logging
|
||||
import bb.utils
|
||||
from bb.parse import ParseError, resolve_file, ast, logger
|
||||
|
||||
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<lazyques>\?\?=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?!'[^']*'[^']*'$)(?!\"[^\"]*\"[^\"]*\"$)(?P<apo>['\"])(?P<value>.*)(?P=apo)$")
|
||||
__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}/]+)(\[(?P<flag>[a-zA-Z0-9\-_+.]+)\])?\s*((?P<colon>:=)|(?P<lazyques>\?\?=)|(?P<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"])(?P<value>.*)(?P=apo)$")
|
||||
__include_regexp__ = re.compile( r"include\s+(.+)" )
|
||||
__require_regexp__ = re.compile( r"require\s+(.+)" )
|
||||
__export_regexp__ = re.compile( r"export\s+([a-zA-Z0-9\-_+.${}/]+)$" )
|
||||
|
||||
@@ -130,7 +130,7 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
|
||||
m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
|
||||
if m:
|
||||
if m.group(1):
|
||||
preferred_e = m.group(1)[:-1]
|
||||
preferred_e = int(m.group(1)[:-1])
|
||||
else:
|
||||
preferred_e = None
|
||||
preferred_v = m.group(2)
|
||||
|
||||
@@ -466,7 +466,7 @@ class RunQueueData:
|
||||
# (makes sure sometask runs after targetname's someothertask)
|
||||
idepends = taskData.tasks_idepends[task]
|
||||
for (depid, idependtask) in idepends:
|
||||
if depid in taskData.build_targets and not depid in taskData.failed_deps:
|
||||
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:
|
||||
@@ -692,14 +692,13 @@ class RunQueueData:
|
||||
stampfnwhitelist.append(fn)
|
||||
self.stampfnwhitelist = stampfnwhitelist
|
||||
|
||||
# Iterate over the task list looking for tasks with a 'setscene' function
|
||||
# Interate over the task list looking for tasks with a 'setscene' function
|
||||
self.runq_setscene = []
|
||||
if not self.cooker.configuration.nosetscene:
|
||||
for task in range(len(self.runq_fnid)):
|
||||
setscene = taskData.gettask_id(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task] + "_setscene", False)
|
||||
if not setscene:
|
||||
continue
|
||||
self.runq_setscene.append(task)
|
||||
for task in range(len(self.runq_fnid)):
|
||||
setscene = taskData.gettask_id(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task] + "_setscene", False)
|
||||
if not setscene:
|
||||
continue
|
||||
self.runq_setscene.append(task)
|
||||
|
||||
def invalidate_task(fn, taskname, error_nostamp):
|
||||
taskdep = self.dataCache.task_deps[fn]
|
||||
@@ -836,6 +835,9 @@ class RunQueue:
|
||||
t1 = get_timestamp(stampfile)
|
||||
for dep in self.rqdata.runq_depends[task]:
|
||||
if iscurrent:
|
||||
if dep in cache:
|
||||
iscurrent = cache[dep]
|
||||
continue
|
||||
fn2 = self.rqdata.taskData.fn_index[self.rqdata.runq_fnid[dep]]
|
||||
taskname2 = self.rqdata.runq_task[dep]
|
||||
stampfile2 = bb.build.stampfile(taskname2, self.rqdata.dataCache, fn2)
|
||||
@@ -852,18 +854,12 @@ 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, cache=cache)
|
||||
cache[dep] = iscurrent
|
||||
cache[task] = iscurrent
|
||||
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
|
||||
@@ -927,19 +923,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 SystemExit:
|
||||
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
|
||||
@@ -1176,8 +1159,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)
|
||||
@@ -1186,7 +1167,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
|
||||
@@ -1197,7 +1178,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]:
|
||||
@@ -1214,30 +1195,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]]
|
||||
@@ -1490,7 +1450,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
|
||||
@@ -1539,12 +1499,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
|
||||
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])
|
||||
@@ -1675,9 +1629,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))
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class ServerCommunicator():
|
||||
if self.connection.poll(.5):
|
||||
return self.connection.recv()
|
||||
else:
|
||||
return None, "Timeout while attempting to communicate with bitbake server"
|
||||
return None
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import hashlib
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
import bb.data
|
||||
|
||||
logger = logging.getLogger('BitBake.SigGen')
|
||||
@@ -48,9 +47,6 @@ class SignatureGenerator(object):
|
||||
def stampfile(self, stampbase, file_name, taskname, extrainfo):
|
||||
return ("%s.%s.%s" % (stampbase, taskname, extrainfo)).rstrip('.')
|
||||
|
||||
def stampcleanmask(self, stampbase, file_name, taskname, extrainfo):
|
||||
return ("%s.%s.%s" % (stampbase, taskname, extrainfo)).rstrip('.')
|
||||
|
||||
def dump_sigtask(self, fn, task, stampbase, runtime):
|
||||
return
|
||||
|
||||
@@ -188,8 +184,8 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
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
|
||||
self.file_checksum_values[k][f] = cs
|
||||
data = data + cs
|
||||
|
||||
taint = self.read_taint(fn, task, dataCache.stamp[fn])
|
||||
if taint:
|
||||
@@ -240,20 +236,10 @@ 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
|
||||
with open(sigfile, "wb") as f:
|
||||
p = pickle.Pickler(f, -1)
|
||||
p.dump(data)
|
||||
os.chmod(sigfile, 0664)
|
||||
|
||||
def dump_sigs(self, dataCache):
|
||||
for fn in self.taskdeps:
|
||||
@@ -269,23 +255,18 @@ class SignatureGeneratorBasic(SignatureGenerator):
|
||||
class SignatureGeneratorBasicHash(SignatureGeneratorBasic):
|
||||
name = "basichash"
|
||||
|
||||
def stampfile(self, stampbase, fn, taskname, extrainfo, clean=False):
|
||||
def stampfile(self, stampbase, fn, taskname, extrainfo):
|
||||
if taskname != "do_setscene" and taskname.endswith("_setscene"):
|
||||
k = fn + "." + taskname[:-9]
|
||||
else:
|
||||
k = fn + "." + taskname
|
||||
if clean:
|
||||
h = "*"
|
||||
elif k in self.taskhash:
|
||||
if k in self.taskhash:
|
||||
h = self.taskhash[k]
|
||||
else:
|
||||
# If k is not in basehash, then error
|
||||
h = self.basehash[k]
|
||||
return ("%s.%s.%s.%s" % (stampbase, taskname, h, extrainfo)).rstrip('.')
|
||||
|
||||
def stampcleanmask(self, stampbase, fn, taskname, extrainfo):
|
||||
return self.stampfile(stampbase, fn, taskname, extrainfo, clean=True)
|
||||
|
||||
def invalidate_task(self, task, d, fn):
|
||||
bb.note("Tainting hash to force rebuild of task %s, %s" % (fn, task))
|
||||
bb.build.write_taint(task, d, fn)
|
||||
@@ -298,7 +279,7 @@ def dump_this_task(outfile, d):
|
||||
|
||||
def clean_basepath(a):
|
||||
if a.startswith("virtual:"):
|
||||
b = a.rsplit(":", 1)[0] + ":" + a.rsplit("/", 1)[1]
|
||||
b = a.rsplit(":", 1)[0] + a.rsplit("/", 1)[1]
|
||||
else:
|
||||
b = a.rsplit("/", 1)[1]
|
||||
return b
|
||||
@@ -309,9 +290,7 @@ def clean_basepaths(a):
|
||||
b[clean_basepath(x)] = a[x]
|
||||
return b
|
||||
|
||||
def compare_sigfiles(a, b, recursecb = None):
|
||||
output = []
|
||||
|
||||
def compare_sigfiles(a, b):
|
||||
p1 = pickle.Unpickler(open(a, "rb"))
|
||||
a_data = p1.load()
|
||||
p2 = pickle.Unpickler(open(b, "rb"))
|
||||
@@ -330,123 +309,114 @@ def compare_sigfiles(a, b, recursecb = None):
|
||||
return changed, added, removed
|
||||
|
||||
if 'basewhitelist' in a_data and a_data['basewhitelist'] != b_data['basewhitelist']:
|
||||
output.append("basewhitelist changed from %s to %s" % (a_data['basewhitelist'], b_data['basewhitelist']))
|
||||
print "basewhitelist changed from %s to %s" % (a_data['basewhitelist'], b_data['basewhitelist'])
|
||||
if a_data['basewhitelist'] and b_data['basewhitelist']:
|
||||
output.append("changed items: %s" % a_data['basewhitelist'].symmetric_difference(b_data['basewhitelist']))
|
||||
print "changed items: %s" % a_data['basewhitelist'].symmetric_difference(b_data['basewhitelist'])
|
||||
|
||||
if 'taskwhitelist' in a_data and a_data['taskwhitelist'] != b_data['taskwhitelist']:
|
||||
output.append("taskwhitelist changed from %s to %s" % (a_data['taskwhitelist'], b_data['taskwhitelist']))
|
||||
print "taskwhitelist changed from %s to %s" % (a_data['taskwhitelist'], b_data['taskwhitelist'])
|
||||
if a_data['taskwhitelist'] and b_data['taskwhitelist']:
|
||||
output.append("changed items: %s" % a_data['taskwhitelist'].symmetric_difference(b_data['taskwhitelist']))
|
||||
print "changed items: %s" % a_data['taskwhitelist'].symmetric_difference(b_data['taskwhitelist'])
|
||||
|
||||
if a_data['taskdeps'] != b_data['taskdeps']:
|
||||
output.append("Task dependencies changed from:\n%s\nto:\n%s" % (sorted(a_data['taskdeps']), sorted(b_data['taskdeps'])))
|
||||
print "Task dependencies changed from:\n%s\nto:\n%s" % (sorted(a_data['taskdeps']), sorted(b_data['taskdeps']))
|
||||
|
||||
if a_data['basehash'] != b_data['basehash']:
|
||||
output.append("basehash changed from %s to %s" % (a_data['basehash'], b_data['basehash']))
|
||||
print "basehash changed from %s to %s" % (a_data['basehash'], b_data['basehash'])
|
||||
|
||||
changed, added, removed = dict_diff(a_data['gendeps'], b_data['gendeps'], a_data['basewhitelist'] & b_data['basewhitelist'])
|
||||
if changed:
|
||||
for dep in changed:
|
||||
output.append("List of dependencies for variable %s changed from %s to %s" % (dep, a_data['gendeps'][dep], b_data['gendeps'][dep]))
|
||||
print "List of dependencies for variable %s changed from %s to %s" % (dep, a_data['gendeps'][dep], b_data['gendeps'][dep])
|
||||
if a_data['gendeps'][dep] and b_data['gendeps'][dep]:
|
||||
output.append("changed items: %s" % a_data['gendeps'][dep].symmetric_difference(b_data['gendeps'][dep]))
|
||||
print "changed items: %s" % a_data['gendeps'][dep].symmetric_difference(b_data['gendeps'][dep])
|
||||
if added:
|
||||
for dep in added:
|
||||
output.append("Dependency on variable %s was added" % (dep))
|
||||
print "Dependency on variable %s was added" % (dep)
|
||||
if removed:
|
||||
for dep in removed:
|
||||
output.append("Dependency on Variable %s was removed" % (dep))
|
||||
print "Dependency on Variable %s was removed" % (dep)
|
||||
|
||||
|
||||
changed, added, removed = dict_diff(a_data['varvals'], b_data['varvals'])
|
||||
if changed:
|
||||
for dep in changed:
|
||||
output.append("Variable %s value changed from %s to %s" % (dep, a_data['varvals'][dep], b_data['varvals'][dep]))
|
||||
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:
|
||||
output.append("Checksum for file %s changed from %s to %s" % (f, a_data['file_checksum_values'][f], b_data['file_checksum_values'][f]))
|
||||
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:
|
||||
output.append("Dependency on checksum of file %s was added" % (f))
|
||||
print "Dependency on checksum of file %s was added" % (f)
|
||||
if removed:
|
||||
for f in removed:
|
||||
output.append("Dependency on checksum of file %s was removed" % (f))
|
||||
print "Dependency on checksum of file %s was removed" % (f)
|
||||
|
||||
|
||||
if 'runtaskhashes' in a_data and 'runtaskhashes' in b_data:
|
||||
a = a_data['runtaskhashes']
|
||||
b = b_data['runtaskhashes']
|
||||
a = clean_basepaths(a_data['runtaskhashes'])
|
||||
b = clean_basepaths(b_data['runtaskhashes'])
|
||||
changed, added, removed = dict_diff(a, b)
|
||||
if added:
|
||||
for dep in added:
|
||||
bdep_found = False
|
||||
if removed:
|
||||
for bdep in removed:
|
||||
if a[dep] == b[bdep]:
|
||||
#output.append("Dependency on task %s was replaced by %s with same hash" % (dep, bdep))
|
||||
bdep_found = True
|
||||
if not bdep_found:
|
||||
output.append("Dependency on task %s was added with hash %s" % (clean_basepath(dep), a[dep]))
|
||||
bdep_found = False
|
||||
if removed:
|
||||
for bdep in removed:
|
||||
if a[dep] == b[bdep]:
|
||||
#print "Dependency on task %s was replaced by %s with same hash" % (dep, bdep)
|
||||
bdep_found = True
|
||||
if not bdep_found:
|
||||
print "Dependency on task %s was added with hash %s" % (dep, a[dep])
|
||||
if removed:
|
||||
for dep in removed:
|
||||
adep_found = False
|
||||
if added:
|
||||
for adep in added:
|
||||
if a[adep] == b[dep]:
|
||||
#output.append("Dependency on task %s was replaced by %s with same hash" % (adep, dep))
|
||||
adep_found = True
|
||||
if not adep_found:
|
||||
output.append("Dependency on task %s was removed with hash %s" % (clean_basepath(dep), b[dep]))
|
||||
adep_found = False
|
||||
if added:
|
||||
for adep in added:
|
||||
if a[adep] == b[dep]:
|
||||
#print "Dependency on task %s was replaced by %s with same hash" % (adep, dep)
|
||||
adep_found = True
|
||||
if not adep_found:
|
||||
print "Dependency on task %s was removed with hash %s" % (dep, b[dep])
|
||||
if changed:
|
||||
for dep in changed:
|
||||
output.append("Hash for dependent task %s changed from %s to %s" % (clean_basepath(dep), a[dep], b[dep]))
|
||||
if callable(recursecb):
|
||||
recout = recursecb(dep, a[dep], b[dep])
|
||||
if recout:
|
||||
output.extend(recout)
|
||||
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:
|
||||
output.append("Taint (by forced/invalidated task) changed from %s to %s" % (a_taint, b_taint))
|
||||
|
||||
return output
|
||||
print "Taint (by forced/invalidated task) changed from %s to %s" % (a_taint, b_taint)
|
||||
|
||||
|
||||
def dump_sigfile(a):
|
||||
output = []
|
||||
|
||||
p1 = pickle.Unpickler(open(a, "rb"))
|
||||
a_data = p1.load()
|
||||
|
||||
output.append("basewhitelist: %s" % (a_data['basewhitelist']))
|
||||
print "basewhitelist: %s" % (a_data['basewhitelist'])
|
||||
|
||||
output.append("taskwhitelist: %s" % (a_data['taskwhitelist']))
|
||||
print "taskwhitelist: %s" % (a_data['taskwhitelist'])
|
||||
|
||||
output.append("Task dependencies: %s" % (sorted(a_data['taskdeps'])))
|
||||
print "Task dependencies: %s" % (sorted(a_data['taskdeps']))
|
||||
|
||||
output.append("basehash: %s" % (a_data['basehash']))
|
||||
print "basehash: %s" % (a_data['basehash'])
|
||||
|
||||
for dep in a_data['gendeps']:
|
||||
output.append("List of dependencies for variable %s is %s" % (dep, a_data['gendeps'][dep]))
|
||||
print "List of dependencies for variable %s is %s" % (dep, a_data['gendeps'][dep])
|
||||
|
||||
for dep in a_data['varvals']:
|
||||
output.append("Variable %s value is %s" % (dep, a_data['varvals'][dep]))
|
||||
print "Variable %s value is %s" % (dep, a_data['varvals'][dep])
|
||||
|
||||
if 'runtaskdeps' in a_data:
|
||||
output.append("Tasks this task depends on: %s" % (a_data['runtaskdeps']))
|
||||
print "Tasks this task depends on: %s" % (a_data['runtaskdeps'])
|
||||
|
||||
if 'file_checksum_values' in a_data:
|
||||
output.append("This task depends on the checksums of files: %s" % (a_data['file_checksum_values']))
|
||||
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']:
|
||||
output.append("Hash for dependent task %s is %s" % (dep, a_data['runtaskhashes'][dep]))
|
||||
print "Hash for dependent task %s is %s" % (dep, a_data['runtaskhashes'][dep])
|
||||
|
||||
if 'taint' in a_data:
|
||||
output.append("Tainted (by forced/invalidated task): %s" % a_data['taint'])
|
||||
|
||||
return output
|
||||
print "Tainted (by forced/invalidated task): %s" % a_data['taint']
|
||||
|
||||
@@ -176,9 +176,6 @@ class TaskData:
|
||||
# Work out task dependencies
|
||||
parentids = []
|
||||
for dep in task_deps['parents'][task]:
|
||||
if dep not in task_deps['tasks']:
|
||||
bb.debug(2, "Not adding dependeny of %s on %s since %s does not exist" % (task, dep, dep))
|
||||
continue
|
||||
parentid = self.gettask_id(fn, dep)
|
||||
parentids.append(parentid)
|
||||
taskid = self.gettask_id(fn, task)
|
||||
|
||||
@@ -34,18 +34,3 @@ class VerCmpString(unittest.TestCase):
|
||||
result = bb.utils.vercmp_string('1.1', '1_p2')
|
||||
self.assertTrue(result < 0)
|
||||
|
||||
def test_explode_dep_versions(self):
|
||||
correctresult = {"foo" : ["= 1.10"]}
|
||||
result = bb.utils.explode_dep_versions2("foo (= 1.10)")
|
||||
self.assertEqual(result, correctresult)
|
||||
result = bb.utils.explode_dep_versions2("foo (=1.10)")
|
||||
self.assertEqual(result, correctresult)
|
||||
result = bb.utils.explode_dep_versions2("foo ( = 1.10)")
|
||||
self.assertEqual(result, correctresult)
|
||||
result = bb.utils.explode_dep_versions2("foo ( =1.10)")
|
||||
self.assertEqual(result, correctresult)
|
||||
result = bb.utils.explode_dep_versions2("foo ( = 1.10 )")
|
||||
self.assertEqual(result, correctresult)
|
||||
result = bb.utils.explode_dep_versions2("foo ( =1.10 )")
|
||||
self.assertEqual(result, correctresult)
|
||||
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
# tinfoil: a simple wrapper around cooker for bitbake-based command-line utilities
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
# Copyright (C) 2011 Mentor Graphics 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 logging
|
||||
import warnings
|
||||
import os
|
||||
import sys
|
||||
|
||||
import bb.cache
|
||||
import bb.cooker
|
||||
import bb.providers
|
||||
import bb.utils
|
||||
from bb.cooker import state
|
||||
import bb.fetch2
|
||||
|
||||
class Tinfoil:
|
||||
def __init__(self):
|
||||
# Needed to avoid deprecation warnings with python 2.6
|
||||
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
||||
|
||||
# Set up logging
|
||||
self.logger = logging.getLogger('BitBake')
|
||||
console = logging.StreamHandler(sys.stdout)
|
||||
format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
|
||||
bb.msg.addDefaultlogFilter(console)
|
||||
console.setFormatter(format)
|
||||
self.logger.addHandler(console)
|
||||
|
||||
initialenv = os.environ.copy()
|
||||
bb.utils.clean_environment()
|
||||
self.config = TinfoilConfig(parse_only=True)
|
||||
self.cooker = bb.cooker.BBCooker(self.config,
|
||||
self.register_idle_function,
|
||||
initialenv)
|
||||
self.config_data = self.cooker.configuration.data
|
||||
bb.providers.logger.setLevel(logging.ERROR)
|
||||
self.cooker_data = None
|
||||
|
||||
def register_idle_function(self, function, data):
|
||||
pass
|
||||
|
||||
def parseRecipes(self):
|
||||
sys.stderr.write("Parsing recipes..")
|
||||
self.logger.setLevel(logging.WARNING)
|
||||
|
||||
try:
|
||||
while self.cooker.state in (state.initial, state.parsing):
|
||||
self.cooker.updateCache()
|
||||
except KeyboardInterrupt:
|
||||
self.cooker.shutdown()
|
||||
self.cooker.updateCache()
|
||||
sys.exit(2)
|
||||
|
||||
self.logger.setLevel(logging.INFO)
|
||||
sys.stderr.write("done.\n")
|
||||
|
||||
self.cooker_data = self.cooker.status
|
||||
|
||||
def prepare(self, config_only = False):
|
||||
if not self.cooker_data:
|
||||
if config_only:
|
||||
self.cooker.parseConfiguration()
|
||||
self.cooker_data = self.cooker.status
|
||||
else:
|
||||
self.parseRecipes()
|
||||
|
||||
|
||||
class TinfoilConfig(object):
|
||||
def __init__(self, **options):
|
||||
self.pkgs_to_build = []
|
||||
self.debug_domains = []
|
||||
self.extra_assume_provided = []
|
||||
self.prefile = []
|
||||
self.postfile = []
|
||||
self.debug = 0
|
||||
self.__dict__.update(options)
|
||||
|
||||
def __getattr__(self, attribute):
|
||||
try:
|
||||
return super(TinfoilConfig, self).__getattribute__(attribute)
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
@@ -25,7 +25,7 @@ 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, HobButton
|
||||
from bb.ui.crumbs.runningbuild import RunningBuildTreeView
|
||||
from bb.ui.crumbs.runningbuild import BuildFailureTreeView
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
@@ -99,8 +99,6 @@ class BuildConfigurationTreeView(gtk.TreeView):
|
||||
import os, os.path
|
||||
if os.path.exists(path):
|
||||
branch = bb.process.run('cd %s; git branch | grep "^* " | tr -d "* "' % path)[0]
|
||||
if branch.startswith("fatal:"):
|
||||
branch = "(unknown)"
|
||||
if branch:
|
||||
branch = branch.strip('\n')
|
||||
vars.append(self.set_vars("Branch:", branch))
|
||||
@@ -167,7 +165,7 @@ class BuildDetailsPage (HobPage):
|
||||
self.builder.handler.build.model.connect_after("row-changed", self.scroll_to_present_row, self.scrolled_view_build.get_vadjustment(), self.build_tv)
|
||||
|
||||
self.button_box = gtk.HBox(False, 6)
|
||||
self.back_button = HobAltButton('<< Back')
|
||||
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)
|
||||
|
||||
@@ -201,133 +199,87 @@ 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
|
||||
def update_failures_sum_display(self):
|
||||
num = 0
|
||||
it = self.failure_model.get_iter_first()
|
||||
while it:
|
||||
color = self.failure_model.get_value(it, self.builder.handler.build.model.COL_COLOR)
|
||||
if color == HobColors.ERROR:
|
||||
num += 1
|
||||
it = self.failure_model.iter_next(it)
|
||||
|
||||
return num
|
||||
|
||||
def add_build_fail_top_bar(self, actions):
|
||||
mainly_action = "Edit %s" % actions
|
||||
if 'image' in actions:
|
||||
next_action = ""
|
||||
else:
|
||||
next_action = "Create new image"
|
||||
|
||||
#set to issue page
|
||||
self.notebook.set_page("Issues")
|
||||
|
||||
color = HobColors.ERROR
|
||||
build_fail_top = gtk.EventBox()
|
||||
#build_fail_top.set_size_request(-1, 200)
|
||||
build_fail_top.set_size_request(-1, 260)
|
||||
build_fail_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
|
||||
|
||||
build_fail_tab = gtk.Table(14, 46, True)
|
||||
build_fail_tab = gtk.Table(7, 40, 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)
|
||||
build_fail_tab.attach(icon, 1, 4, 0, 3)
|
||||
|
||||
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.set_markup("<span size='x-large'>%s</span>" % self.title)
|
||||
build_fail_tab.attach(label, 4, 20, 0, 3)
|
||||
|
||||
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)
|
||||
num_of_fails = self.update_failures_sum_display()
|
||||
current_fail, recipe_task_status = self.task_status.get_text().split('\n')
|
||||
label.set_markup(" %d tasks failed, %s, %s" % (num_of_fails, current_fail, recipe_task_status))
|
||||
build_fail_tab.attach(label, 4, 40, 2, 4)
|
||||
|
||||
# create button 'Edit packages'
|
||||
action_button = HobButton(primary_action)
|
||||
#action_button.set_size_request(-1, 40)
|
||||
action_button.set_tooltip_text("Edit the %s parameters" % actions)
|
||||
action_button.connect('clicked', self.failure_primary_action_button_clicked_cb, primary_action)
|
||||
build_fail_tab.attach(action_button, 4, 13, 9, 12)
|
||||
action_button = HobButton(mainly_action)
|
||||
action_button.set_size_request(-1, 49)
|
||||
action_button.connect('clicked', self.failure_main_action_button_clicked_cb, mainly_action)
|
||||
build_fail_tab.attach(action_button, 4, 16, 4, 6)
|
||||
|
||||
if log_file:
|
||||
open_log_button = HobAltButton("Open log")
|
||||
open_log_button.set_relief(gtk.RELIEF_HALF)
|
||||
open_log_button.set_tooltip_text("Open the build's log file")
|
||||
open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
|
||||
build_fail_tab.attach(open_log_button, 14, 23, 9, 12)
|
||||
if next_action:
|
||||
next_button = HobAltButton(next_action)
|
||||
next_button.set_alignment(0.0, 0.5)
|
||||
next_button.connect('clicked', self.failure_next_action_button_clicked_cb, next_action)
|
||||
build_fail_tab.attach(next_button, 17, 24, 4, 5)
|
||||
|
||||
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.set_tooltip_text("Open the Yocto Project bug tracking website")
|
||||
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)
|
||||
file_bug_button.set_alignment(0.0, 0.5)
|
||||
file_bug_button.connect('clicked', self.failure_file_bug_activate_link_cb)
|
||||
build_fail_tab.attach(file_bug_button, 17, 24, 4 + abs(next_action != ""), 6)
|
||||
|
||||
return build_fail_top
|
||||
|
||||
def show_fail_page(self, title):
|
||||
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(title, self.builder.current_logfile)
|
||||
|
||||
self.build_fail_bar = self.add_build_fail_top_bar(action_names)
|
||||
self.pack_start(self.build_fail_bar)
|
||||
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 add_build_stop_top_bar(self, action, log_file=None):
|
||||
color = HobColors.LIGHT_GRAY
|
||||
build_stop_top = gtk.EventBox()
|
||||
#build_stop_top.set_size_request(-1, 200)
|
||||
build_stop_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
|
||||
build_stop_top.set_flags(gtk.CAN_DEFAULT)
|
||||
build_stop_top.grab_default()
|
||||
|
||||
build_stop_tab = gtk.Table(11, 46, True)
|
||||
build_stop_top.add(build_stop_tab)
|
||||
|
||||
icon = gtk.Image()
|
||||
icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INFO_HOVER_FILE)
|
||||
icon.set_from_pixbuf(icon_pix_buffer)
|
||||
build_stop_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_stop_tab.attach(label, 4, 26, 0, 6)
|
||||
|
||||
action_button = HobButton("Edit %s" % action)
|
||||
action_button.set_size_request(-1, 40)
|
||||
if action == "image":
|
||||
action_button.set_tooltip_text("Edit the image parameters")
|
||||
elif action == "recipes":
|
||||
action_button.set_tooltip_text("Edit the included recipes")
|
||||
elif action == "packages":
|
||||
action_button.set_tooltip_text("Edit the included packages")
|
||||
action_button.connect('clicked', self.stop_primary_action_button_clicked_cb, action)
|
||||
build_stop_tab.attach(action_button, 4, 13, 6, 9)
|
||||
|
||||
if log_file:
|
||||
open_log_button = HobAltButton("Open log")
|
||||
open_log_button.set_relief(gtk.RELIEF_HALF)
|
||||
open_log_button.set_tooltip_text("Open the build's log file")
|
||||
open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
|
||||
build_stop_tab.attach(open_log_button, 14, 23, 6, 9)
|
||||
|
||||
attach_pos = (24 if log_file else 14)
|
||||
build_button = HobAltButton("Build new image")
|
||||
#build_button.set_size_request(-1, 40)
|
||||
build_button.set_tooltip_text("Create a new image from scratch")
|
||||
build_button.connect('clicked', self.new_image_button_clicked_cb)
|
||||
build_stop_tab.attach(build_button, attach_pos, attach_pos + 9, 6, 9)
|
||||
|
||||
return build_stop_top, action_button
|
||||
|
||||
def show_stop_page(self, action):
|
||||
self._remove_all_widget()
|
||||
self.title = "Build stopped"
|
||||
self.build_stop_bar, action_button = self.add_build_stop_top_bar(action, self.builder.current_logfile)
|
||||
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
self.box_group_area.pack_start(self.build_stop_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.show_all()
|
||||
self.back_button.hide()
|
||||
return action_button
|
||||
|
||||
def show_page(self, step):
|
||||
self._remove_all_widget()
|
||||
if step == self.builder.PACKAGE_GENERATING or step == self.builder.FAST_IMAGE_GENERATING:
|
||||
@@ -361,9 +313,6 @@ class BuildDetailsPage (HobPage):
|
||||
def back_button_clicked_cb(self, button):
|
||||
self.builder.show_configuration()
|
||||
|
||||
def new_image_button_clicked_cb(self, button):
|
||||
self.builder.reset()
|
||||
|
||||
def show_back_button(self):
|
||||
self.back_button.show()
|
||||
|
||||
@@ -385,25 +334,17 @@ 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):
|
||||
def failure_main_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" in action:
|
||||
elif "Edit image configuration" in action:
|
||||
self.builder.show_configuration()
|
||||
|
||||
def stop_primary_action_button_clicked_cb(self, button, action):
|
||||
if "recipes" in action:
|
||||
self.builder.show_recipes()
|
||||
elif "packages" in action:
|
||||
self.builder.show_packages(ask=False)
|
||||
elif "image" in action:
|
||||
self.builder.show_configuration()
|
||||
def failure_next_action_button_clicked_cb(self, button, action):
|
||||
if "Create new image" in action:
|
||||
self.builder.initiate_new_build_async()
|
||||
|
||||
def 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):
|
||||
def failure_file_bug_activate_link_cb(self, button):
|
||||
button.child.emit('activate-link', "http://bugzilla.yoctoproject.org")
|
||||
|
||||
@@ -21,30 +21,26 @@
|
||||
# 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, gobject
|
||||
import gtk
|
||||
import copy
|
||||
import os
|
||||
import subprocess
|
||||
import shlex
|
||||
import re
|
||||
import logging
|
||||
import sys
|
||||
from bb.ui.crumbs.template import TemplateMgr
|
||||
from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
|
||||
from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
|
||||
from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
|
||||
from bb.ui.crumbs.builddetailspage import BuildDetailsPage
|
||||
from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
|
||||
from bb.ui.crumbs.sanitycheckpage import SanityCheckPage
|
||||
from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
|
||||
from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton, hcc
|
||||
from bb.ui.crumbs.hig import CrumbsMessageDialog, ImageSelectionDialog, \
|
||||
AdvancedSettingDialog, SimpleSettingsDialog, \
|
||||
LayerSelectionDialog, DeployImageDialog
|
||||
AdvancedSettingDialog, LayerSelectionDialog, \
|
||||
DeployImageDialog
|
||||
from bb.ui.crumbs.persistenttooltip import PersistentTooltip
|
||||
import bb.ui.crumbs.utils
|
||||
|
||||
hobVer = 20120808
|
||||
hobVer = 20120530
|
||||
|
||||
class Configuration:
|
||||
'''Represents the data structure of configuration.'''
|
||||
@@ -126,8 +122,6 @@ class Configuration:
|
||||
self.selected_image = None
|
||||
self.selected_recipes = []
|
||||
self.selected_packages = []
|
||||
self.initial_selected_packages = []
|
||||
self.initial_user_selected_packages = []
|
||||
|
||||
def split_proxy(self, protocol, proxy):
|
||||
entry = []
|
||||
@@ -189,7 +183,7 @@ class Configuration:
|
||||
self.curr_distro = template.getVar("DISTRO")
|
||||
self.dldir = template.getVar("DL_DIR")
|
||||
self.sstatedir = template.getVar("SSTATE_DIR")
|
||||
self.sstatemirror = template.getVar("SSTATE_MIRRORS")
|
||||
self.sstatemirror = template.getVar("SSTATE_MIRROR")
|
||||
try:
|
||||
self.pmake = int(template.getVar("PARALLEL_MAKE").split()[1])
|
||||
except:
|
||||
@@ -239,7 +233,7 @@ class Configuration:
|
||||
template.setVar("DISTRO", self.curr_distro)
|
||||
template.setVar("DL_DIR", self.dldir)
|
||||
template.setVar("SSTATE_DIR", self.sstatedir)
|
||||
template.setVar("SSTATE_MIRRORS", self.sstatemirror)
|
||||
template.setVar("SSTATE_MIRROR", self.sstatemirror)
|
||||
template.setVar("PARALLEL_MAKE", "-j %s" % self.pmake)
|
||||
template.setVar("BB_NUMBER_THREADS", self.bbthread)
|
||||
template.setVar("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]))
|
||||
@@ -268,22 +262,6 @@ class Configuration:
|
||||
template.setVar("CVS_PROXY_HOST", self.combine_host_only("cvs"))
|
||||
template.setVar("CVS_PROXY_PORT", self.combine_port_only("cvs"))
|
||||
|
||||
def __str__(self):
|
||||
s = "VERSION: '%s', BBLAYERS: '%s', MACHINE: '%s', DISTRO: '%s', DL_DIR: '%s'," % \
|
||||
(hobVer, " ".join(self.layers), self.curr_mach, self.curr_distro, self.dldir )
|
||||
s += "SSTATE_DIR: '%s', SSTATE_MIRROR: '%s', PARALLEL_MAKE: '-j %s', BB_NUMBER_THREADS: '%s', PACKAGE_CLASSES: '%s', " % \
|
||||
(self.sstatedir, self.sstatemirror, self.pmake, self.bbthread, " ".join(["package_" + i for i in self.curr_package_format.split()]))
|
||||
s += "IMAGE_ROOTFS_SIZE: '%s', IMAGE_EXTRA_SPACE: '%s', INCOMPATIBLE_LICENSE: '%s', SDKMACHINE: '%s', CONF_VERSION: '%s', " % \
|
||||
(self.image_rootfs_size, self.image_extra_size, self.incompat_license, self.curr_sdk_machine, self.conf_version)
|
||||
s += "LCONF_VERSION: '%s', EXTRA_SETTING: '%s', TOOLCHAIN_BUILD: '%s', IMAGE_FSTYPES: '%s', __SELECTED_IMAGE__: '%s', " % \
|
||||
(self.lconf_version, self.extra_setting, self.toolchain_build, self.image_fstypes, self.selected_image)
|
||||
s += "DEPENDS: '%s', IMAGE_INSTALL: '%s', enable_proxy: '%s', use_same_proxy: '%s', http_proxy: '%s', " % \
|
||||
(self.selected_recipes, self.user_selected_packages, self.enable_proxy, self.same_proxy, self.combine_proxy("http"))
|
||||
s += "https_proxy: '%s', ftp_proxy: '%s', GIT_PROXY_HOST: '%s', GIT_PROXY_PORT: '%s', CVS_PROXY_HOST: '%s', CVS_PROXY_PORT: '%s'" % \
|
||||
(self.combine_proxy("https"), self.combine_proxy("ftp"),self.combine_host_only("git"), self.combine_port_only("git"),
|
||||
self.combine_host_only("cvs"), self.combine_port_only("cvs"))
|
||||
return s
|
||||
|
||||
class Parameters:
|
||||
'''Represents other variables like available machines, etc.'''
|
||||
|
||||
@@ -344,7 +322,7 @@ def hob_conf_filter(fn, data):
|
||||
|
||||
keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
|
||||
"BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
|
||||
"SSTATE_DIR_HOB", "SSTATE_MIRRORS_HOB", "INCOMPATIBLE_LICENSE_HOB"]
|
||||
"SSTATE_DIR_HOB", "SSTATE_MIRROR_HOB", "INCOMPATIBLE_LICENSE_HOB"]
|
||||
for key in keys:
|
||||
var_hob = data.getVar(key)
|
||||
if var_hob:
|
||||
@@ -359,8 +337,7 @@ def hob_conf_filter(fn, data):
|
||||
|
||||
class Builder(gtk.Window):
|
||||
|
||||
(INITIAL_CHECKS,
|
||||
MACHINE_SELECTION,
|
||||
(MACHINE_SELECTION,
|
||||
RCPPKGINFO_POPULATING,
|
||||
RCPPKGINFO_POPULATED,
|
||||
BASEIMG_SELECTED,
|
||||
@@ -373,18 +350,16 @@ class Builder(gtk.Window):
|
||||
IMAGE_GENERATED,
|
||||
MY_IMAGE_OPENED,
|
||||
BACK,
|
||||
END_NOOP) = range(15)
|
||||
END_NOOP) = range(14)
|
||||
|
||||
(SANITY_CHECK,
|
||||
IMAGE_CONFIGURATION,
|
||||
(IMAGE_CONFIGURATION,
|
||||
RECIPE_DETAILS,
|
||||
BUILD_DETAILS,
|
||||
PACKAGE_DETAILS,
|
||||
IMAGE_DETAILS,
|
||||
END_TAB) = range(7)
|
||||
END_TAB) = range(6)
|
||||
|
||||
__step2page__ = {
|
||||
INITIAL_CHECKS : SANITY_CHECK,
|
||||
MACHINE_SELECTION : IMAGE_CONFIGURATION,
|
||||
RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
|
||||
RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
|
||||
@@ -400,7 +375,14 @@ class Builder(gtk.Window):
|
||||
END_NOOP : None,
|
||||
}
|
||||
|
||||
SANITY_CHECK_MIN_DISPLAY_TIME = 5
|
||||
@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__()
|
||||
@@ -413,11 +395,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()
|
||||
@@ -453,10 +430,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)
|
||||
@@ -474,14 +449,8 @@ class Builder(gtk.Window):
|
||||
self.set_title("Hob")
|
||||
self.set_icon_name("applications-development")
|
||||
self.set_resizable(True)
|
||||
|
||||
try:
|
||||
window_width = self.get_screen().get_width()
|
||||
window_height = self.get_screen().get_height()
|
||||
except AttributeError:
|
||||
print "Please set DISPLAY variable before running Hob."
|
||||
sys.exit(1)
|
||||
|
||||
window_width = self.get_screen().get_width()
|
||||
window_height = self.get_screen().get_height()
|
||||
if window_width >= hwc.MAIN_WIN_WIDTH:
|
||||
window_width = hwc.MAIN_WIN_WIDTH
|
||||
window_height = hwc.MAIN_WIN_HEIGHT
|
||||
@@ -497,14 +466,9 @@ class Builder(gtk.Window):
|
||||
self.build_details_page = BuildDetailsPage(self)
|
||||
self.package_details_page = PackageSelectionPage(self)
|
||||
self.image_details_page = ImageDetailsPage(self)
|
||||
self.sanity_check_page = SanityCheckPage(self)
|
||||
self.display_sanity_check = False
|
||||
self.sanity_check_post_func = False
|
||||
self.had_network_error = False
|
||||
|
||||
self.nb = gtk.Notebook()
|
||||
self.nb.set_show_tabs(False)
|
||||
self.nb.insert_page(self.sanity_check_page, None, self.SANITY_CHECK)
|
||||
self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
|
||||
self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
|
||||
self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
|
||||
@@ -515,46 +479,17 @@ class Builder(gtk.Window):
|
||||
self.show_all()
|
||||
self.nb.set_current_page(0)
|
||||
|
||||
def sanity_check_timeout(self):
|
||||
# The minimum time for showing the 'sanity check' page has passe
|
||||
# If someone set the 'sanity_check_post_step' meanwhile, execute it now
|
||||
self.display_sanity_check = False
|
||||
if self.sanity_check_post_func:
|
||||
temp = self.sanity_check_post_func
|
||||
self.sanity_check_post_func = None
|
||||
temp()
|
||||
return False
|
||||
|
||||
def show_sanity_check_page(self):
|
||||
# This window must stay on screen for at least 5 seconds, according to the design document
|
||||
self.nb.set_current_page(self.SANITY_CHECK)
|
||||
self.sanity_check_post_step = None
|
||||
self.display_sanity_check = True
|
||||
self.sanity_check_page.start()
|
||||
gobject.timeout_add(self.SANITY_CHECK_MIN_DISPLAY_TIME * 1000, self.sanity_check_timeout)
|
||||
|
||||
def execute_after_sanity_check(self, func):
|
||||
if not self.display_sanity_check:
|
||||
func()
|
||||
else:
|
||||
sanity_check_post_func = func
|
||||
|
||||
def generate_configuration(self):
|
||||
self.show_sanity_check_page()
|
||||
self.handler.generate_configuration()
|
||||
|
||||
def initiate_new_build_async(self):
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
if self.load_template(TemplateMgr.convert_to_template_pathfilename("default", ".hob/")) == False:
|
||||
self.show_sanity_check_page()
|
||||
self.handler.init_cooker()
|
||||
self.handler.set_extra_inherit("image_types")
|
||||
self.generate_configuration()
|
||||
self.handler.generate_configuration()
|
||||
|
||||
def update_config_async(self):
|
||||
self.switch_page(self.MACHINE_SELECTION)
|
||||
self.set_user_config()
|
||||
self.generate_configuration()
|
||||
self.handler.generate_configuration()
|
||||
|
||||
def sanity_check(self):
|
||||
self.handler.trigger_sanity_check()
|
||||
@@ -565,41 +500,25 @@ 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 restore_initial_selected_packages(self):
|
||||
self.package_model.set_selected_packages(self.configuration.initial_user_selected_packages, True)
|
||||
self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
|
||||
for package in self.configuration.selected_packages:
|
||||
if package not in self.configuration.initial_selected_packages:
|
||||
self.package_model.exclude_item(self.package_model.find_path_for_item(package))
|
||||
|
||||
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 = []
|
||||
@@ -704,33 +623,17 @@ class Builder(gtk.Window):
|
||||
self.image_configuration_page.show_baseimg_selected()
|
||||
|
||||
elif next_step == self.RECIPE_SELECTION:
|
||||
if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
|
||||
self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
|
||||
else:
|
||||
self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
|
||||
pass
|
||||
|
||||
elif next_step == self.PACKAGE_SELECTION:
|
||||
self.configuration.initial_selected_packages = self.configuration.selected_packages
|
||||
self.configuration.initial_user_selected_packages = self.configuration.user_selected_packages
|
||||
self.package_details_page.set_title("Edit packages")
|
||||
if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
|
||||
self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
|
||||
else:
|
||||
self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
|
||||
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_GENERATING and FAST_IMAGE_GENERATING share the same page
|
||||
# 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.set_title("Step 2 of 2: Edit packages")
|
||||
if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
|
||||
self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
|
||||
else:
|
||||
self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
|
||||
self.package_details_page.show_page(self.current_logfile)
|
||||
pass
|
||||
|
||||
elif next_step == self.IMAGE_GENERATING:
|
||||
# after packages are generated, selected_packages need to
|
||||
@@ -756,7 +659,7 @@ class Builder(gtk.Window):
|
||||
self.handler.set_distro(self.configuration.curr_distro)
|
||||
self.handler.set_dl_dir(self.configuration.dldir)
|
||||
self.handler.set_sstate_dir(self.configuration.sstatedir)
|
||||
self.handler.set_sstate_mirrors(self.configuration.sstatemirror)
|
||||
self.handler.set_sstate_mirror(self.configuration.sstatemirror)
|
||||
self.handler.set_pmake(self.configuration.pmake)
|
||||
self.handler.set_bbthreads(self.configuration.bbthread)
|
||||
self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
|
||||
@@ -785,10 +688,7 @@ class Builder(gtk.Window):
|
||||
self.recipe_model.set_selected_image(selected_image)
|
||||
self.recipe_model.set_selected_recipes(selected_recipes)
|
||||
|
||||
def update_package_model(self, selected_packages, user_selected_packages=None):
|
||||
if user_selected_packages:
|
||||
left = self.package_model.set_selected_packages(user_selected_packages, True)
|
||||
self.configuration.user_selected_packages += left
|
||||
def update_package_model(self, selected_packages):
|
||||
left = self.package_model.set_selected_packages(selected_packages)
|
||||
self.configuration.selected_packages += left
|
||||
|
||||
@@ -816,29 +716,12 @@ class Builder(gtk.Window):
|
||||
def handler_package_formats_updated_cb(self, handler, formats):
|
||||
self.parameters.all_package_formats = formats
|
||||
|
||||
def switch_to_image_configuration_helper(self):
|
||||
self.sanity_check_page.stop()
|
||||
self.switch_page(self.IMAGE_CONFIGURATION)
|
||||
self.image_configuration_page.switch_machine_combo()
|
||||
|
||||
def show_network_error_dialog_helper(self):
|
||||
self.sanity_check_page.stop()
|
||||
self.show_network_error_dialog()
|
||||
|
||||
def handler_command_succeeded_cb(self, handler, initcmd):
|
||||
if initcmd == self.handler.GENERATE_CONFIGURATION:
|
||||
if not self.configuration.curr_mach:
|
||||
self.configuration.curr_mach = self.handler.runCommand(["getVariable", "HOB_MACHINE"]) or ""
|
||||
self.update_configuration_parameters(self.get_parameters_sync())
|
||||
self.sanity_check()
|
||||
elif initcmd == self.handler.SANITY_CHECK:
|
||||
if self.had_network_error:
|
||||
self.had_network_error = False
|
||||
self.execute_after_sanity_check(self.show_network_error_dialog_helper)
|
||||
else:
|
||||
# Switch to the 'image configuration' page now, but we might need
|
||||
# to wait for the minimum display time of the sanity check page
|
||||
self.execute_after_sanity_check(self.switch_to_image_configuration_helper)
|
||||
self.image_configuration_page.switch_machine_combo()
|
||||
elif initcmd in [self.handler.GENERATE_RECIPES,
|
||||
self.handler.GENERATE_PACKAGES,
|
||||
self.handler.GENERATE_IMAGE]:
|
||||
@@ -852,50 +735,26 @@ 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>Hob found an error</b>\n"
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR, msg)
|
||||
lbl = "<b>Error</b>\n"
|
||||
lbl = lbl + "%s\n\n" % Builder.interpret_markup(msg)
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
|
||||
def show_network_error_dialog(self):
|
||||
lbl = "<b>Hob cannot connect to the network</b>\n"
|
||||
msg = "Please check your network connection. If you are using a proxy server, please make sure it is configured correctly."
|
||||
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)
|
||||
button = dialog.add_button("Proxy settings", gtk.RESPONSE_CANCEL)
|
||||
HobButton.style_button(button)
|
||||
res = dialog.run()
|
||||
dialog.destroy()
|
||||
if res == gtk.RESPONSE_CANCEL:
|
||||
res, settings_changed = self.show_simple_settings_dialog(SimpleSettingsDialog.PROXIES_PAGE_ID)
|
||||
if not res:
|
||||
return
|
||||
if settings_changed:
|
||||
self.reparse_post_adv_settings()
|
||||
|
||||
def handler_command_failed_cb(self, handler, msg):
|
||||
if msg:
|
||||
self.show_error_dialog(msg)
|
||||
self.reset()
|
||||
|
||||
def handler_sanity_failed_cb(self, handler, msg, network_error):
|
||||
def handler_sanity_failed_cb(self, handler, msg):
|
||||
msg = msg.replace("your local.conf", "Settings")
|
||||
self.show_error_dialog(msg)
|
||||
self.reset()
|
||||
if network_error:
|
||||
# Mark this in an internal field. The "network error" dialog will be
|
||||
# shown later, when a SanityCheckPassed event will be handled
|
||||
# (as sent by sanity.bbclass)
|
||||
self.had_network_error = True
|
||||
else:
|
||||
msg = msg.replace("your local.conf", "Settings")
|
||||
self.show_error_dialog(msg)
|
||||
self.reset()
|
||||
|
||||
def window_sensitive(self, sensitive):
|
||||
self.image_configuration_page.machine_combo.set_sensitive(sensitive)
|
||||
@@ -905,7 +764,8 @@ class Builder(gtk.Window):
|
||||
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)
|
||||
self.image_configuration_page.view_adv_configuration_button.set_sensitive(sensitive)
|
||||
self.image_configuration_page.view_recipes_button.set_sensitive(sensitive)
|
||||
self.image_configuration_page.view_packages_button.set_sensitive(sensitive)
|
||||
self.image_configuration_page.config_build_button.set_sensitive(sensitive)
|
||||
|
||||
self.recipe_details_page.set_sensitive(sensitive)
|
||||
@@ -914,9 +774,9 @@ class Builder(gtk.Window):
|
||||
self.image_details_page.set_sensitive(sensitive)
|
||||
|
||||
if sensitive:
|
||||
self.window.set_cursor(None)
|
||||
self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
|
||||
else:
|
||||
self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
||||
self.get_root_window().set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
|
||||
self.sensitive = sensitive
|
||||
|
||||
|
||||
@@ -930,12 +790,11 @@ class Builder(gtk.Window):
|
||||
selected_image = self.configuration.selected_image
|
||||
selected_recipes = self.configuration.selected_recipes[:]
|
||||
selected_packages = self.configuration.selected_packages[:]
|
||||
user_selected_packages = self.configuration.user_selected_packages[:]
|
||||
|
||||
self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
|
||||
self.image_configuration_page.update_image_desc()
|
||||
self.update_recipe_model(selected_image, selected_recipes)
|
||||
self.update_package_model(selected_packages, user_selected_packages)
|
||||
self.update_package_model(selected_packages)
|
||||
|
||||
def recipelist_changed_cb(self, recipe_model):
|
||||
self.recipe_details_page.refresh_selection()
|
||||
@@ -1007,13 +866,8 @@ class Builder(gtk.Window):
|
||||
linkname = 'hob-image-' + self.configuration.curr_mach
|
||||
else:
|
||||
linkname = selected_image + '-' + self.configuration.curr_mach
|
||||
image_extension = self.get_image_extension()
|
||||
for image_type in self.parameters.image_types:
|
||||
if image_type in image_extension:
|
||||
real_types = image_extension[image_type]
|
||||
else:
|
||||
real_types = [image_type]
|
||||
for real_image_type in real_types:
|
||||
for real_image_type in hcc.SUPPORTED_IMAGE_TYPES[image_type]:
|
||||
linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
|
||||
if os.path.exists(linkpath):
|
||||
self.parameters.image_names.append(os.readlink(linkpath))
|
||||
@@ -1033,18 +887,6 @@ class Builder(gtk.Window):
|
||||
status = "stop"
|
||||
message = "Build stopped: "
|
||||
fraction = self.build_details_page.progress_bar.get_fraction()
|
||||
stop_to_next_edit = ""
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
stop_to_next_edit = "image configuration"
|
||||
elif self.current_step == self.IMAGE_GENERATING:
|
||||
if self.previous_step == self.FAST_IMAGE_GENERATING:
|
||||
stop_to_next_edit = "image configuration"
|
||||
else:
|
||||
stop_to_next_edit = "packages"
|
||||
elif self.current_step == self.PACKAGE_GENERATING:
|
||||
stop_to_next_edit = "recipes"
|
||||
button = self.build_details_page.show_stop_page(stop_to_next_edit.split(' ')[0])
|
||||
self.set_default(button)
|
||||
else:
|
||||
fail_to_next_edit = ""
|
||||
if self.current_step == self.FAST_IMAGE_GENERATING:
|
||||
@@ -1059,7 +901,7 @@ class Builder(gtk.Window):
|
||||
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])
|
||||
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)
|
||||
@@ -1078,11 +920,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, glib.markup_escape_text(msg), gtk.STOCK_DIALOG_INFO)
|
||||
dialog = CrumbsMessageDialog(self, Builder.interpret_markup(msg), gtk.STOCK_DIALOG_INFO)
|
||||
button = dialog.add_button("Close", gtk.RESPONSE_OK)
|
||||
HobButton.style_button(button)
|
||||
dialog.run()
|
||||
@@ -1120,18 +959,23 @@ 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
|
||||
elif self.handler.building:
|
||||
self.stop_build()
|
||||
return True
|
||||
else:
|
||||
lbl = "<b>Do you really want to exit the Hob image creator?</b>"
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Exit Hob", gtk.RESPONSE_YES)
|
||||
HobButton.style_button(button)
|
||||
dialog.set_default_response(gtk.RESPONSE_YES)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response == gtk.RESPONSE_YES:
|
||||
gtk.main_quit()
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def build_packages(self):
|
||||
_, all_recipes = self.recipe_model.get_selected_recipes()
|
||||
@@ -1144,7 +988,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()
|
||||
@@ -1157,7 +1001,7 @@ 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()
|
||||
@@ -1174,7 +1018,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
|
||||
@@ -1236,21 +1080,10 @@ class Builder(gtk.Window):
|
||||
self.save_template(path)
|
||||
dialog.destroy()
|
||||
|
||||
def get_image_extension(self):
|
||||
image_extension = {}
|
||||
for type in self.parameters.image_types:
|
||||
ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
|
||||
if ext:
|
||||
image_extension[type] = ext.split(' ')
|
||||
|
||||
return image_extension
|
||||
|
||||
def show_load_my_images_dialog(self):
|
||||
image_extension = self.get_image_extension()
|
||||
dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
|
||||
"Open My Images", self,
|
||||
gtk.FILE_CHOOSER_ACTION_SAVE, None,
|
||||
image_extension)
|
||||
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)
|
||||
@@ -1273,8 +1106,8 @@ class Builder(gtk.Window):
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def show_adv_settings_dialog(self, tab=None):
|
||||
dialog = AdvancedSettingDialog(title = "Advanced configuration",
|
||||
def show_adv_settings_dialog(self):
|
||||
dialog = AdvancedSettingDialog(title = "Settings",
|
||||
configuration = copy.deepcopy(self.configuration),
|
||||
all_image_types = self.parameters.image_types,
|
||||
all_package_formats = self.parameters.all_package_formats,
|
||||
@@ -1289,34 +1122,6 @@ class Builder(gtk.Window):
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Save", gtk.RESPONSE_YES)
|
||||
HobButton.style_button(button)
|
||||
dialog.set_save_button(button)
|
||||
response = dialog.run()
|
||||
settings_changed = False
|
||||
if response == gtk.RESPONSE_YES:
|
||||
self.configuration = dialog.configuration
|
||||
self.save_defaults() # remember settings
|
||||
settings_changed = dialog.settings_changed
|
||||
dialog.destroy()
|
||||
return response == gtk.RESPONSE_YES, settings_changed
|
||||
|
||||
def show_simple_settings_dialog(self, tab=None):
|
||||
dialog = SimpleSettingsDialog(title = "Settings",
|
||||
configuration = copy.deepcopy(self.configuration),
|
||||
all_image_types = self.parameters.image_types,
|
||||
all_package_formats = self.parameters.all_package_formats,
|
||||
all_distros = self.parameters.all_distros,
|
||||
all_sdk_machines = self.parameters.all_sdk_machines,
|
||||
max_threads = self.parameters.max_threads,
|
||||
parent = self,
|
||||
flags = gtk.DIALOG_MODAL
|
||||
| gtk.DIALOG_DESTROY_WITH_PARENT
|
||||
| gtk.DIALOG_NO_SEPARATOR)
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Save", gtk.RESPONSE_YES)
|
||||
HobButton.style_button(button)
|
||||
if tab:
|
||||
dialog.switch_to_page(tab)
|
||||
response = dialog.run()
|
||||
settings_changed = False
|
||||
if response == gtk.RESPONSE_YES:
|
||||
@@ -1432,7 +1237,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:
|
||||
@@ -1441,9 +1246,6 @@ class Builder(gtk.Window):
|
||||
def show_recipes(self):
|
||||
self.switch_page(self.RECIPE_SELECTION)
|
||||
|
||||
def show_image_details(self):
|
||||
self.switch_page(self.IMAGE_GENERATED)
|
||||
|
||||
def show_configuration(self):
|
||||
self.switch_page(self.BASEIMG_SELECTED)
|
||||
|
||||
@@ -1461,40 +1263,25 @@ class Builder(gtk.Window):
|
||||
HobButton.style_button(button)
|
||||
else:
|
||||
lbl = "<b>Stop build?</b>\n\nAre you sure you want to stop this"
|
||||
lbl = lbl + " build?\n\n'Stop' will stop the build as soon as all in"
|
||||
lbl = lbl + " build?\n\n'Force Stop' will stop the build as quickly as"
|
||||
lbl = lbl + " possible but may well leave your build directory in an"
|
||||
lbl = lbl + " unusable state that requires manual steps to fix.\n\n"
|
||||
lbl = lbl + "'Stop' will stop the build as soon as all in"
|
||||
lbl = lbl + " progress build tasks are finished. However if a"
|
||||
lbl = lbl + " lengthy compilation phase is in progress this may take"
|
||||
lbl = lbl + " some time.\n\n"
|
||||
lbl = lbl + "'Force Stop' will stop the build as quickly as"
|
||||
lbl = lbl + " possible but may well leave your build directory in an"
|
||||
lbl = lbl + " unusable state that requires manual steps to fix."
|
||||
lbl = lbl + " some time."
|
||||
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Force stop", gtk.RESPONSE_YES)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Stop", gtk.RESPONSE_OK)
|
||||
HobAltButton.style_button(button)
|
||||
button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
|
||||
HobButton.style_button(button)
|
||||
response = dialog.run()
|
||||
dialog.destroy()
|
||||
if response != gtk.RESPONSE_CANCEL:
|
||||
self.stopping = True
|
||||
if response == gtk.RESPONSE_OK:
|
||||
self.build_details_page.progress_bar.set_title("Stopping the build...")
|
||||
self.build_details_page.progress_bar.set_rcstyle("stop")
|
||||
self.cancel_build_sync()
|
||||
elif response == gtk.RESPONSE_YES:
|
||||
self.cancel_build_sync(True)
|
||||
|
||||
def do_log(self, consolelogfile = None):
|
||||
if consolelogfile:
|
||||
bb.utils.mkdirhier(os.path.dirname(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)
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import gobject
|
||||
import logging
|
||||
from bb.ui.crumbs.runningbuild import RunningBuild
|
||||
from bb.ui.crumbs.hobwidget import hcc
|
||||
|
||||
class HobHandler(gobject.GObject):
|
||||
|
||||
@@ -43,7 +44,7 @@ class HobHandler(gobject.GObject):
|
||||
(gobject.TYPE_STRING,)),
|
||||
"sanity-failed" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_STRING, gobject.TYPE_INT)),
|
||||
(gobject.TYPE_STRING,)),
|
||||
"generating-data" : (gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
()),
|
||||
@@ -101,10 +102,7 @@ class HobHandler(gobject.GObject):
|
||||
|
||||
def runCommand(self, commandline):
|
||||
try:
|
||||
result, error = self.server.runCommand(commandline)
|
||||
if error:
|
||||
raise Exception("Error running command '%s': %s" % (commandline, error))
|
||||
return result
|
||||
return self.server.runCommand(commandline)
|
||||
except Exception as e:
|
||||
self.commands_async = []
|
||||
self.clear_busy()
|
||||
@@ -159,16 +157,10 @@ class HobHandler(gobject.GObject):
|
||||
targets.append(self.toolchain)
|
||||
self.runCommand(["buildTargets", targets, self.default_task])
|
||||
|
||||
def display_error(self):
|
||||
self.clear_busy()
|
||||
self.emit("command-failed", self.error_msg)
|
||||
self.error_msg = ""
|
||||
if self.building:
|
||||
self.building = False
|
||||
|
||||
def handle_event(self, event):
|
||||
if not event:
|
||||
return
|
||||
|
||||
if self.building:
|
||||
self.current_phase = "building"
|
||||
self.build.handle_event(event)
|
||||
@@ -182,14 +174,11 @@ class HobHandler(gobject.GObject):
|
||||
self.run_next_command()
|
||||
|
||||
elif isinstance(event, bb.event.SanityCheckFailed):
|
||||
self.emit("sanity-failed", event._msg, event._network_error)
|
||||
self.emit("sanity-failed", event._msg)
|
||||
|
||||
elif isinstance(event, logging.LogRecord):
|
||||
if not self.building:
|
||||
if event.levelno >= logging.ERROR:
|
||||
formatter = bb.msg.BBLogFormatter()
|
||||
msg = formatter.format(event)
|
||||
self.error_msg += msg + '\n'
|
||||
if event.levelno >= logging.ERROR:
|
||||
self.error_msg += event.msg + '\n'
|
||||
|
||||
elif isinstance(event, bb.event.TargetsTreeGenerated):
|
||||
self.current_phase = "data generation"
|
||||
@@ -221,7 +210,11 @@ class HobHandler(gobject.GObject):
|
||||
self.run_next_command()
|
||||
elif isinstance(event, bb.command.CommandFailed):
|
||||
self.commands_async = []
|
||||
self.display_error()
|
||||
self.clear_busy()
|
||||
self.emit("command-failed", self.error_msg)
|
||||
self.error_msg = ""
|
||||
if self.building:
|
||||
self.building = False
|
||||
elif isinstance(event, (bb.event.ParseStarted,
|
||||
bb.event.CacheLoadStarted,
|
||||
bb.event.TreeDataPreparationStarted,
|
||||
@@ -251,9 +244,6 @@ class HobHandler(gobject.GObject):
|
||||
message["title"] = "Parsing recipes: "
|
||||
self.emit("parsing-completed", message)
|
||||
|
||||
if self.error_msg and not self.commands_async:
|
||||
self.display_error()
|
||||
|
||||
return
|
||||
|
||||
def init_cooker(self):
|
||||
@@ -299,8 +289,8 @@ class HobHandler(gobject.GObject):
|
||||
def set_sstate_dir(self, directory):
|
||||
self.runCommand(["setVariable", "SSTATE_DIR_HOB", directory])
|
||||
|
||||
def set_sstate_mirrors(self, url):
|
||||
self.runCommand(["setVariable", "SSTATE_MIRRORS_HOB", url])
|
||||
def set_sstate_mirror(self, url):
|
||||
self.runCommand(["setVariable", "SSTATE_MIRROR_HOB", url])
|
||||
|
||||
def set_extra_size(self, image_extra_size):
|
||||
self.runCommand(["setVariable", "IMAGE_ROOTFS_EXTRA_SPACE", str(image_extra_size)])
|
||||
@@ -400,9 +390,6 @@ class HobHandler(gobject.GObject):
|
||||
def reset_build(self):
|
||||
self.build.reset()
|
||||
|
||||
def get_logfile(self):
|
||||
return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0]
|
||||
|
||||
def _remove_redundant(self, string):
|
||||
ret = []
|
||||
for i in string.split():
|
||||
@@ -423,7 +410,7 @@ class HobHandler(gobject.GObject):
|
||||
params["distro"] = self.runCommand(["getVariable", "DISTRO"]) or "defaultsetup"
|
||||
params["pclass"] = self.runCommand(["getVariable", "PACKAGE_CLASSES"]) or ""
|
||||
params["sstatedir"] = self.runCommand(["getVariable", "SSTATE_DIR"]) or ""
|
||||
params["sstatemirror"] = self.runCommand(["getVariable", "SSTATE_MIRRORS"]) or ""
|
||||
params["sstatemirror"] = self.runCommand(["getVariable", "SSTATE_MIRROR"]) or ""
|
||||
|
||||
num_threads = self.runCommand(["getCpuCount"])
|
||||
if not num_threads:
|
||||
|
||||
@@ -42,7 +42,7 @@ class PackageListModel(gtk.TreeStore):
|
||||
()),
|
||||
}
|
||||
|
||||
__toolchain_required_packages__ = ["packagegroup-core-standalone-sdk-target", "packagegroup-core-standalone-sdk-target-dbg"]
|
||||
__toolchain_required_packages__ = ["task-core-standalone-sdk-target", "task-core-standalone-sdk-target-dbg"]
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@@ -145,12 +145,6 @@ class PackageListModel(gtk.TreeStore):
|
||||
self.pkg_path = {}
|
||||
self.rprov_pkg = {}
|
||||
|
||||
def getpkgvalue(pkgdict, key, pkgname, defaultval = None):
|
||||
value = pkgdict.get('%s_%s' % (key, pkgname), None)
|
||||
if not value:
|
||||
value = pkgdict.get(key, defaultval)
|
||||
return value
|
||||
|
||||
for pkginfo in pkginfolist:
|
||||
pn = pkginfo['PN']
|
||||
pv = pkginfo['PV']
|
||||
@@ -163,24 +157,25 @@ class PackageListModel(gtk.TreeStore):
|
||||
self.COL_INC, False)
|
||||
self.pn_path[pn] = self.get_path(pniter)
|
||||
|
||||
# PKG is always present
|
||||
pkg = pkginfo['PKG']
|
||||
pkgv = getpkgvalue(pkginfo, 'PKGV', pkg)
|
||||
pkgr = getpkgvalue(pkginfo, 'PKGR', pkg)
|
||||
# PKGSIZE is artificial, will always be overridden with the package name if present
|
||||
pkgsize = pkginfo.get('PKGSIZE_%s' % pkg, "0")
|
||||
# PKG_%s is the renamed version
|
||||
pkg_rename = pkginfo.get('PKG_%s' % pkg, "")
|
||||
# The rest may be overridden or not
|
||||
section = getpkgvalue(pkginfo, 'SECTION', pkg, "")
|
||||
summary = getpkgvalue(pkginfo, 'SUMMARY', pkg, "")
|
||||
rdep = getpkgvalue(pkginfo, 'RDEPENDS', pkg, "")
|
||||
rrec = getpkgvalue(pkginfo, 'RRECOMMENDS', pkg, "")
|
||||
rprov = getpkgvalue(pkginfo, 'RPROVIDES', pkg, "")
|
||||
pkgv = pkginfo['PKGV']
|
||||
pkgr = pkginfo['PKGR']
|
||||
pkgsize = pkginfo['PKGSIZE_%s' % pkg] if 'PKGSIZE_%s' % pkg in pkginfo.keys() else "0"
|
||||
pkg_rename = pkginfo['PKG_%s' % pkg] if 'PKG_%s' % pkg in pkginfo.keys() else ""
|
||||
section = pkginfo['SECTION_%s' % pkg] if 'SECTION_%s' % pkg in pkginfo.keys() else ""
|
||||
summary = pkginfo['SUMMARY_%s' % pkg] if 'SUMMARY_%s' % pkg in pkginfo.keys() else ""
|
||||
rdep = pkginfo['RDEPENDS_%s' % pkg] if 'RDEPENDS_%s' % pkg in pkginfo.keys() else ""
|
||||
rrec = pkginfo['RRECOMMENDS_%s' % pkg] if 'RRECOMMENDS_%s' % pkg in pkginfo.keys() else ""
|
||||
rprov = pkginfo['RPROVIDES_%s' % pkg] if 'RPROVIDES_%s' % pkg in pkginfo.keys() else ""
|
||||
for i in rprov.split():
|
||||
self.rprov_pkg[i] = pkg
|
||||
|
||||
allow_empty = getpkgvalue(pkginfo, 'ALLOW_EMPTY', pkg, "")
|
||||
if 'ALLOW_EMPTY_%s' % pkg in pkginfo.keys():
|
||||
allow_empty = pkginfo['ALLOW_EMPTY_%s' % pkg]
|
||||
elif 'ALLOW_EMPTY' in pkginfo.keys():
|
||||
allow_empty = pkginfo['ALLOW_EMPTY']
|
||||
else:
|
||||
allow_empty = ""
|
||||
|
||||
if pkgsize == "0" and not allow_empty:
|
||||
continue
|
||||
@@ -337,13 +332,13 @@ class PackageListModel(gtk.TreeStore):
|
||||
set_selected_packages(), some packages will not be set included.
|
||||
Return the un-set packages list.
|
||||
"""
|
||||
def set_selected_packages(self, packagelist, user_selected=False):
|
||||
def set_selected_packages(self, packagelist):
|
||||
left = []
|
||||
binb = 'User Selected' if user_selected else ''
|
||||
for pn in packagelist:
|
||||
if pn in self.pkg_path.keys():
|
||||
path = self.pkg_path[pn]
|
||||
self.include_item(item_path=path, binb=binb)
|
||||
self.include_item(item_path=path,
|
||||
binb="User Selected")
|
||||
else:
|
||||
left.append(pn)
|
||||
|
||||
@@ -359,7 +354,7 @@ class PackageListModel(gtk.TreeStore):
|
||||
while child_it:
|
||||
if self.get_value(child_it, self.COL_INC):
|
||||
binb = self.get_value(child_it, self.COL_BINB)
|
||||
if binb == "User Selected":
|
||||
if not binb or binb == "User Selected":
|
||||
name = self.get_value(child_it, self.COL_NAME)
|
||||
packagelist.append(name)
|
||||
child_it = self.iter_next(child_it)
|
||||
@@ -526,24 +521,17 @@ class RecipeListModel(gtk.ListStore):
|
||||
val2 = model.get_value(iter2, RecipeListModel.COL_INC)
|
||||
return ((val1 == True) and (val2 == False))
|
||||
|
||||
def include_item_sort_func(self, model, iter1, iter2):
|
||||
val1 = model.get_value(iter1, RecipeListModel.COL_INC)
|
||||
val2 = model.get_value(iter2, RecipeListModel.COL_INC)
|
||||
return ((val1 == False) and (val2 == True))
|
||||
|
||||
"""
|
||||
Create, if required, and return a filtered gtk.TreeModelSort
|
||||
containing only the items which are items specified by filter
|
||||
"""
|
||||
def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=True):
|
||||
def tree_model(self, filter, excluded_items_ahead=False):
|
||||
model = self.filter_new()
|
||||
model.set_visible_func(self.tree_model_filter, filter)
|
||||
|
||||
sort = gtk.TreeModelSort(model)
|
||||
if excluded_items_ahead:
|
||||
sort.set_default_sort_func(self.exclude_item_sort_func)
|
||||
elif included_items_ahead:
|
||||
sort.set_default_sort_func(self.include_item_sort_func)
|
||||
else:
|
||||
sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING)
|
||||
sort.set_default_sort_func(None)
|
||||
@@ -578,8 +566,9 @@ class RecipeListModel(gtk.ListStore):
|
||||
|
||||
# dummy image for prompt
|
||||
self.set(self.append(), self.COL_NAME, self.__custom_image__,
|
||||
self.COL_DESC, "Use 'Edit image' to customize recipes and packages " \
|
||||
"to be included in your 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,
|
||||
@@ -595,8 +584,8 @@ class RecipeListModel(gtk.ListStore):
|
||||
|
||||
depends = event_model["depends"].get(item, []) + event_model["rdepends-pn"].get(item, [])
|
||||
|
||||
if ('packagegroup.bbclass' in " ".join(inherits)):
|
||||
atype = 'packagegroup'
|
||||
if ('task-' in name):
|
||||
atype = 'task'
|
||||
elif ('image.bbclass' in " ".join(inherits)):
|
||||
if name != "hob-image":
|
||||
atype = 'image'
|
||||
@@ -672,10 +661,6 @@ class RecipeListModel(gtk.ListStore):
|
||||
self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
elif not dep_included:
|
||||
self.include_item(dep_path, binb=item_name, image_contents=image_contents)
|
||||
dep_bin = self[item_path][self.COL_BINB].split(', ')
|
||||
if self[item_path][self.COL_NAME] in dep_bin:
|
||||
dep_bin.remove(self[item_path][self.COL_NAME])
|
||||
self[item_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
|
||||
|
||||
def exclude_item(self, item_path):
|
||||
if not self.path_included(item_path):
|
||||
|
||||
@@ -38,7 +38,6 @@ class HobPage (gtk.VBox):
|
||||
self.title = "Hob -- Image Creator"
|
||||
else:
|
||||
self.title = title
|
||||
self.title_label = gtk.Label()
|
||||
|
||||
self.box_group_area = gtk.VBox(False, 12)
|
||||
self.box_group_area.set_size_request(self.builder_width - 73 - 73, self.builder_height - 88 - 15 - 15)
|
||||
@@ -47,9 +46,6 @@ class HobPage (gtk.VBox):
|
||||
self.group_align.add(self.box_group_area)
|
||||
self.box_group_area.set_homogeneous(False)
|
||||
|
||||
def set_title(self, title):
|
||||
self.title = title
|
||||
self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
|
||||
|
||||
def add_onto_top_bar(self, widget = None, padding = 0):
|
||||
# the top button occupies 1/7 of the page height
|
||||
@@ -62,9 +58,9 @@ class HobPage (gtk.VBox):
|
||||
|
||||
hbox = gtk.HBox()
|
||||
|
||||
self.title_label = gtk.Label()
|
||||
self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
|
||||
hbox.pack_start(self.title_label, expand=False, fill=False, padding=20)
|
||||
label = gtk.Label()
|
||||
label.set_markup("<span size='x-large'>%s</span>" % self.title)
|
||||
hbox.pack_start(label, expand=False, fill=False, padding=20)
|
||||
|
||||
if widget:
|
||||
# add the widget in the event box
|
||||
|
||||
@@ -63,6 +63,35 @@ class hic:
|
||||
ICON_INDI_TICK_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/tick.png'))
|
||||
ICON_INDI_INFO_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/info.png'))
|
||||
|
||||
class hcc:
|
||||
|
||||
SUPPORTED_IMAGE_TYPES = {
|
||||
"jffs2" : ["jffs2"],
|
||||
"sum.jffs2" : ["sum.jffs2"],
|
||||
"cramfs" : ["cramfs"],
|
||||
"ext2" : ["ext2"],
|
||||
"ext2.gz" : ["ext2.gz"],
|
||||
"ext2.bz2" : ["ext2.bz2"],
|
||||
"ext3" : ["ext3"],
|
||||
"ext3.gz" : ["ext3.gz"],
|
||||
"ext2.lzma" : ["ext2.lzma"],
|
||||
"btrfs" : ["btrfs"],
|
||||
"live" : ["hddimg", "iso"],
|
||||
"squashfs" : ["squashfs"],
|
||||
"squashfs-lzma" : ["squashfs-lzma"],
|
||||
"ubi" : ["ubi"],
|
||||
"tar" : ["tar"],
|
||||
"tar.gz" : ["tar.gz"],
|
||||
"tar.bz2" : ["tar.bz2"],
|
||||
"tar.xz" : ["tar.xz"],
|
||||
"cpio" : ["cpio"],
|
||||
"cpio.gz" : ["cpio.gz"],
|
||||
"cpio.xz" : ["cpio.xz"],
|
||||
"vmdk" : ["vmdk"],
|
||||
"cpio.lzma" : ["cpio.lzma"],
|
||||
"elf" : ["elf"],
|
||||
}
|
||||
|
||||
class HobViewTable (gtk.VBox):
|
||||
"""
|
||||
A VBox to contain the table for different recipe views and package view
|
||||
@@ -153,12 +182,7 @@ class HobViewTable (gtk.VBox):
|
||||
# Just display the first item
|
||||
if binb:
|
||||
bin = binb.split(', ')
|
||||
total_no = len(bin)
|
||||
if total_no > 1 and bin[0] == "User Selected":
|
||||
present_binb = bin[1] + ' (+' + str(total_no) + ')'
|
||||
else:
|
||||
present_binb = bin[0] + ' (+' + str(total_no) + ')'
|
||||
cell.set_property('text', present_binb)
|
||||
cell.set_property('text', bin[0])
|
||||
else:
|
||||
cell.set_property('text', "")
|
||||
return True
|
||||
@@ -219,7 +243,7 @@ def soften_color(widget, state=gtk.STATE_NORMAL):
|
||||
color.blue = color.blue * blend + style.base[state].blue * (1.0 - blend)
|
||||
return color.to_string()
|
||||
|
||||
class BaseHobButton(gtk.Button):
|
||||
class HobButton(gtk.Button):
|
||||
"""
|
||||
A gtk.Button subclass which follows the visual design of Hob for primary
|
||||
action buttons
|
||||
@@ -233,33 +257,24 @@ class BaseHobButton(gtk.Button):
|
||||
@staticmethod
|
||||
def style_button(button):
|
||||
style = button.get_style()
|
||||
style = gtk.rc_get_style_by_paths(gtk.settings_get_default(), 'gtk-button', 'gtk-button', gobject.TYPE_NONE)
|
||||
button_color = gtk.gdk.Color(HobColors.ORANGE)
|
||||
button.modify_bg(gtk.STATE_NORMAL, button_color)
|
||||
button.modify_bg(gtk.STATE_PRELIGHT, button_color)
|
||||
button.modify_bg(gtk.STATE_SELECTED, button_color)
|
||||
|
||||
button.set_flags(gtk.CAN_DEFAULT)
|
||||
button.grab_default()
|
||||
|
||||
# label = "<span size='x-large'><b>%s</b></span>" % gobject.markup_escape_text(button.get_label())
|
||||
label = button.get_label()
|
||||
label = "<span size='x-large'><b>%s</b></span>" % gobject.markup_escape_text(button.get_label())
|
||||
button.set_label(label)
|
||||
button.child.set_use_markup(True)
|
||||
|
||||
class HobButton(BaseHobButton):
|
||||
"""
|
||||
A gtk.Button subclass which follows the visual design of Hob for primary
|
||||
action buttons
|
||||
|
||||
label: the text to display as the button's label
|
||||
"""
|
||||
def __init__(self, label):
|
||||
BaseHobButton.__init__(self, label)
|
||||
HobButton.style_button(self)
|
||||
|
||||
class HobAltButton(BaseHobButton):
|
||||
class HobAltButton(gtk.Button):
|
||||
"""
|
||||
A gtk.Button subclass which has no relief, and so is more discrete
|
||||
"""
|
||||
def __init__(self, label):
|
||||
BaseHobButton.__init__(self, label)
|
||||
gtk.Button.__init__(self, label)
|
||||
HobAltButton.style_button(self)
|
||||
|
||||
"""
|
||||
@@ -285,6 +300,14 @@ class HobAltButton(BaseHobButton):
|
||||
button.set_label("<span size='large' color='%s'><b>%s</b></span>" % (colour, gobject.markup_escape_text(button.text)))
|
||||
button.child.set_use_markup(True)
|
||||
|
||||
@staticmethod
|
||||
def style_button(button):
|
||||
button.text = button.get_label()
|
||||
button.connect("state-changed", HobAltButton.desensitise_on_state_change_cb)
|
||||
HobAltButton.set_text(button)
|
||||
button.child.set_use_markup(True)
|
||||
button.set_relief(gtk.RELIEF_NONE)
|
||||
|
||||
class HobImageButton(gtk.Button):
|
||||
"""
|
||||
A gtk.Button with an icon and two rows of text, the second of which is
|
||||
@@ -337,8 +360,7 @@ class HobInfoButton(gtk.EventBox):
|
||||
def __init__(self, tip_markup, parent=None):
|
||||
gtk.EventBox.__init__(self)
|
||||
self.image = gtk.Image()
|
||||
self.image.set_from_file(
|
||||
hic.ICON_INFO_DISPLAY_FILE)
|
||||
self.image.set_from_file(hic.ICON_INFO_DISPLAY_FILE)
|
||||
self.image.show()
|
||||
self.add(self.image)
|
||||
|
||||
|
||||
@@ -135,9 +135,8 @@ class ImageConfigurationPage (HobPage):
|
||||
self._pack_components(pack_config_build_button = True)
|
||||
self.set_config_machine_layout(show_progress_bar = False)
|
||||
self.set_config_baseimg_layout()
|
||||
self.set_rcppkg_layout()
|
||||
self.show_all()
|
||||
if self.builder.recipe_model.get_selected_image() == self.builder.recipe_model.__custom_image__:
|
||||
self.just_bake_button.hide()
|
||||
|
||||
def create_config_machine(self):
|
||||
self.machine_title = gtk.Label()
|
||||
@@ -167,12 +166,13 @@ class ImageConfigurationPage (HobPage):
|
||||
markup += "dev-manual.html#understanding-and-using-layers\">reference manual</a>."
|
||||
self.layer_info_icon = HobInfoButton(markup, self.get_parent())
|
||||
|
||||
# self.progress_box = gtk.HBox(False, 6)
|
||||
self.progress_box = gtk.HBox(False, 6)
|
||||
self.progress_bar = HobProgressBar()
|
||||
# self.progress_box.pack_start(self.progress_bar, expand=True, fill=True)
|
||||
self.progress_box.pack_start(self.progress_bar, expand=True, fill=True)
|
||||
self.stop_button = HobAltButton("Stop")
|
||||
self.stop_button.connect("clicked", self.stop_button_clicked_cb)
|
||||
# self.progress_box.pack_end(stop_button, expand=False, fill=False)
|
||||
self.progress_box.pack_end(self.stop_button, expand=False, fill=False)
|
||||
|
||||
self.machine_separator = gtk.HSeparator()
|
||||
|
||||
def set_config_machine_layout(self, show_progress_bar = False):
|
||||
@@ -182,9 +182,7 @@ class ImageConfigurationPage (HobPage):
|
||||
self.gtable.attach(self.layer_button, 14, 36, 7, 12)
|
||||
self.gtable.attach(self.layer_info_icon, 36, 40, 7, 11)
|
||||
if show_progress_bar:
|
||||
#self.gtable.attach(self.progress_box, 0, 40, 15, 18)
|
||||
self.gtable.attach(self.progress_bar, 0, 37, 15, 18)
|
||||
self.gtable.attach(self.stop_button, 37, 40, 15, 18, 0, 0)
|
||||
self.gtable.attach(self.progress_box, 0, 40, 15, 19)
|
||||
self.gtable.attach(self.machine_separator, 0, 40, 13, 14)
|
||||
|
||||
def create_config_baseimg(self):
|
||||
@@ -205,17 +203,25 @@ class ImageConfigurationPage (HobPage):
|
||||
|
||||
self.image_desc = gtk.Label()
|
||||
self.image_desc.set_alignment(0.0, 0.5)
|
||||
self.image_desc.set_size_request(256, -1)
|
||||
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
|
||||
icon_file = hic.ICON_RCIPE_DISPLAY_FILE
|
||||
hover_file = hic.ICON_RCIPE_HOVER_FILE
|
||||
self.view_adv_configuration_button = HobImageButton("Advanced configuration",
|
||||
"Select image types, package formats, etc",
|
||||
icon_file, hover_file)
|
||||
self.view_adv_configuration_button.connect("clicked", self.view_adv_configuration_button_clicked_cb)
|
||||
self.view_recipes_button = HobImageButton("View recipes",
|
||||
"Add/remove recipes and tasks",
|
||||
icon_file, hover_file)
|
||||
self.view_recipes_button.connect("clicked", self.view_recipes_button_clicked_cb)
|
||||
|
||||
# button to view packages
|
||||
icon_file = hic.ICON_PACKAGES_DISPLAY_FILE
|
||||
hover_file = hic.ICON_PACKAGES_HOVER_FILE
|
||||
self.view_packages_button = HobImageButton("View packages",
|
||||
"Add/remove previously built packages",
|
||||
icon_file, hover_file)
|
||||
self.view_packages_button.connect("clicked", self.view_packages_button_clicked_cb)
|
||||
|
||||
self.image_separator = gtk.HSeparator()
|
||||
|
||||
@@ -223,27 +229,32 @@ class ImageConfigurationPage (HobPage):
|
||||
self.gtable.attach(self.image_title, 0, 40, 15, 17)
|
||||
self.gtable.attach(self.image_title_desc, 0, 40, 18, 22)
|
||||
self.gtable.attach(self.image_combo, 0, 12, 23, 26)
|
||||
self.gtable.attach(self.image_desc, 0, 12, 27, 33)
|
||||
self.gtable.attach(self.view_adv_configuration_button, 14, 36, 23, 28)
|
||||
self.gtable.attach(self.image_desc, 13, 38, 23, 28)
|
||||
self.gtable.attach(self.image_separator, 0, 40, 35, 36)
|
||||
|
||||
def set_rcppkg_layout(self):
|
||||
self.gtable.attach(self.view_recipes_button, 0, 20, 28, 33)
|
||||
self.gtable.attach(self.view_packages_button, 20, 40, 28, 33)
|
||||
|
||||
def create_config_build_button(self):
|
||||
# Create the "Build packages" and "Build image" buttons at the bottom
|
||||
button_box = gtk.HBox(False, 6)
|
||||
|
||||
# create button "Build image"
|
||||
self.just_bake_button = HobButton("Build image")
|
||||
#self.just_bake_button.set_size_request(205, 49)
|
||||
self.just_bake_button.set_tooltip_text("Build target image")
|
||||
self.just_bake_button.connect("clicked", self.just_bake_button_clicked_cb)
|
||||
button_box.pack_end(self.just_bake_button, expand=False, fill=False)
|
||||
just_bake_button = HobButton("Build image")
|
||||
just_bake_button.set_size_request(205, 49)
|
||||
just_bake_button.set_tooltip_text("Build target image")
|
||||
just_bake_button.connect("clicked", self.just_bake_button_clicked_cb)
|
||||
button_box.pack_end(just_bake_button, expand=False, fill=False)
|
||||
|
||||
# create button "Edit Image"
|
||||
self.edit_image_button = HobAltButton("Edit image")
|
||||
#self.edit_image_button.set_size_request(205, 49)
|
||||
self.edit_image_button.set_tooltip_text("Edit target image")
|
||||
self.edit_image_button.connect("clicked", self.edit_image_button_clicked_cb)
|
||||
button_box.pack_end(self.edit_image_button, expand=False, fill=False)
|
||||
label = gtk.Label(" or ")
|
||||
button_box.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Build Packages"
|
||||
build_packages_button = HobAltButton("Build packages")
|
||||
build_packages_button.connect("clicked", self.build_packages_button_clicked_cb)
|
||||
build_packages_button.set_tooltip_text("Build recipes into packages")
|
||||
button_box.pack_end(build_packages_button, expand=False, fill=False)
|
||||
|
||||
return button_box
|
||||
|
||||
@@ -336,9 +347,6 @@ class ImageConfigurationPage (HobPage):
|
||||
|
||||
self.show_baseimg_selected()
|
||||
|
||||
if selected_image == self.builder.recipe_model.__custom_image__:
|
||||
self.just_bake_button.hide()
|
||||
|
||||
glib.idle_add(self.image_combo_changed_idle_cb, selected_image, selected_recipes, selected_packages)
|
||||
|
||||
def _image_combo_connect_signal(self):
|
||||
@@ -355,7 +363,6 @@ class ImageConfigurationPage (HobPage):
|
||||
# populate image combo
|
||||
filter = {RecipeListModel.COL_TYPE : ['image']}
|
||||
image_model = recipe_model.tree_model(filter)
|
||||
image_model.set_sort_column_id(recipe_model.COL_NAME, gtk.SORT_ASCENDING)
|
||||
active = 0
|
||||
cnt = 1
|
||||
|
||||
@@ -368,7 +375,6 @@ class ImageConfigurationPage (HobPage):
|
||||
if self.builder.parameters.image_black_pattern:
|
||||
for i in self.builder.parameters.image_black_pattern.split():
|
||||
black_pattern.append(re.compile(i))
|
||||
black_pattern.append(re.compile("hob-image"))
|
||||
|
||||
it = image_model.get_iter_first()
|
||||
self._image_combo_disconnect_signal()
|
||||
@@ -419,20 +425,18 @@ class ImageConfigurationPage (HobPage):
|
||||
def layer_button_clicked_cb(self, button):
|
||||
# Create a layer selection dialog
|
||||
self.builder.show_layer_selection_dialog()
|
||||
|
||||
def view_adv_configuration_button_clicked_cb(self, button):
|
||||
# Create an advanced settings dialog
|
||||
response, settings_changed = self.builder.show_adv_settings_dialog()
|
||||
if not response:
|
||||
return
|
||||
if settings_changed:
|
||||
self.builder.reparse_post_adv_settings()
|
||||
|
||||
def view_recipes_button_clicked_cb(self, button):
|
||||
self.builder.show_recipes()
|
||||
|
||||
def view_packages_button_clicked_cb(self, button):
|
||||
self.builder.show_packages()
|
||||
|
||||
def just_bake_button_clicked_cb(self, button):
|
||||
self.builder.just_bake()
|
||||
|
||||
def edit_image_button_clicked_cb(self, button):
|
||||
self.builder.show_recipes()
|
||||
def build_packages_button_clicked_cb(self, button):
|
||||
self.builder.build_packages()
|
||||
|
||||
def template_button_clicked_cb(self, button):
|
||||
response, path = self.builder.show_load_template_dialog()
|
||||
@@ -446,7 +450,7 @@ class ImageConfigurationPage (HobPage):
|
||||
|
||||
def settings_button_clicked_cb(self, button):
|
||||
# Create an advanced settings dialog
|
||||
response, settings_changed = self.builder.show_simple_settings_dialog()
|
||||
response, settings_changed = self.builder.show_adv_settings_dialog()
|
||||
if not response:
|
||||
return
|
||||
if settings_changed:
|
||||
|
||||
@@ -33,7 +33,7 @@ from bb.ui.crumbs.hig import CrumbsDialog
|
||||
class ImageDetailsPage (HobPage):
|
||||
|
||||
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
|
||||
@@ -41,10 +41,10 @@ class ImageDetailsPage (HobPage):
|
||||
style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
|
||||
self.set_style(style)
|
||||
|
||||
self.row = gtk.Table(1, 2, False)
|
||||
self.row.set_border_width(10)
|
||||
self.add(self.row)
|
||||
|
||||
self.hbox = gtk.HBox()
|
||||
self.hbox.set_border_width(10)
|
||||
self.add(self.hbox)
|
||||
|
||||
total_rows = 0
|
||||
if widget:
|
||||
total_rows = 10
|
||||
@@ -54,8 +54,8 @@ class ImageDetailsPage (HobPage):
|
||||
self.table = gtk.Table(total_rows, 20, True)
|
||||
self.table.set_row_spacings(6)
|
||||
self.table.set_size_request(100, -1)
|
||||
self.row.attach(self.table, 0, 1, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL)
|
||||
|
||||
self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)
|
||||
|
||||
colid = 0
|
||||
rowid = 0
|
||||
self.line_widgets = {}
|
||||
@@ -72,81 +72,8 @@ class ImageDetailsPage (HobPage):
|
||||
self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
|
||||
# pack the button on the right
|
||||
if button:
|
||||
self.bbox = gtk.VBox()
|
||||
self.bbox.pack_start(button, expand=True, fill=False)
|
||||
if button2:
|
||||
self.bbox.pack_start(button2, expand=True, fill=False)
|
||||
self.bbox.set_size_request(150,-1)
|
||||
self.row.attach(self.bbox, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.EXPAND)
|
||||
|
||||
def update_line_widgets(self, variable, value):
|
||||
if len(self.line_widgets) == 0:
|
||||
return
|
||||
if not isinstance(self.line_widgets[variable], gtk.Label):
|
||||
return
|
||||
self.line_widgets[variable].set_markup(self.format_line(variable, value))
|
||||
self.hbox.pack_end(button, expand=False, fill=False)
|
||||
|
||||
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
|
||||
return markup
|
||||
|
||||
def text2label(self, variable, value):
|
||||
# append the name:value to the left box
|
||||
# such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_markup(self.format_line(variable, value))
|
||||
return label
|
||||
|
||||
class BuildDetailBox (gtk.EventBox):
|
||||
def __init__(self, varlist = None, vallist = None, icon = None, color = HobColors.LIGHT_GRAY):
|
||||
gtk.EventBox.__init__(self)
|
||||
|
||||
# set color
|
||||
style = self.get_style().copy()
|
||||
style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
|
||||
self.set_style(style)
|
||||
|
||||
self.hbox = gtk.HBox()
|
||||
self.hbox.set_border_width(10)
|
||||
self.add(self.hbox)
|
||||
|
||||
total_rows = 0
|
||||
if 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)
|
||||
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 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)
|
||||
|
||||
def update_line_widgets(self, variable, value):
|
||||
if len(self.line_widgets) == 0:
|
||||
return
|
||||
@@ -237,10 +164,8 @@ class ImageDetailsPage (HobPage):
|
||||
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():
|
||||
@@ -252,7 +177,7 @@ class ImageDetailsPage (HobPage):
|
||||
self.pack_start(self.group_align, expand=True, fill=True)
|
||||
|
||||
self.build_result = None
|
||||
if self.build_succeeded and self.builder.current_step == self.builder.IMAGE_GENERATING:
|
||||
if self.build_succeeded:
|
||||
# building is the previous step
|
||||
icon = gtk.Image()
|
||||
pixmap_path = hic.ICON_INDI_CONFIRM_FILE
|
||||
@@ -261,7 +186,7 @@ class ImageDetailsPage (HobPage):
|
||||
icon.set_from_pixbuf(pix_buffer)
|
||||
varlist = [""]
|
||||
vallist = ["Your image is ready"]
|
||||
self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color)
|
||||
self.build_result = self.DetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color)
|
||||
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()
|
||||
@@ -308,7 +233,7 @@ class ImageDetailsPage (HobPage):
|
||||
is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image)
|
||||
|
||||
# Generated image files info
|
||||
varlist = ["Name: ", "Files created: ", "Directory: "]
|
||||
varlist = ["Name: ", "FileCreated: ", "Directory: "]
|
||||
vallist = []
|
||||
|
||||
vallist.append(image_name.split('.')[0])
|
||||
@@ -318,29 +243,23 @@ class ImageDetailsPage (HobPage):
|
||||
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")
|
||||
open_log_button = None
|
||||
if log_file:
|
||||
open_log_button = HobAltButton("Open log")
|
||||
open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
|
||||
open_log_button.set_tooltip_text("Open the build's log file")
|
||||
self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=open_log_button)
|
||||
self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_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)
|
||||
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=True, fill=True)
|
||||
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)
|
||||
|
||||
# Machine, Base image and Layers
|
||||
layer_num_limit = 15
|
||||
@@ -385,7 +304,7 @@ class ImageDetailsPage (HobPage):
|
||||
else: # get to this page from "My images"
|
||||
edit_packages_button = None
|
||||
self.package_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_packages_button)
|
||||
self.box_group_area.pack_start(self.package_detail, expand=True, fill=True)
|
||||
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:
|
||||
@@ -396,16 +315,12 @@ class ImageDetailsPage (HobPage):
|
||||
self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False)
|
||||
|
||||
self.show_all()
|
||||
if self.kernel_detail and (not is_runnable):
|
||||
if 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 open_log_clicked_cb(self, button, log_file):
|
||||
if log_file:
|
||||
os.system("xdg-open /%s" % log_file)
|
||||
|
||||
def refresh_package_detail_box(self, image_size):
|
||||
self.package_detail.update_line_widgets("Total image size: ", image_size)
|
||||
|
||||
@@ -426,8 +341,6 @@ class ImageDetailsPage (HobPage):
|
||||
return mach_runnable
|
||||
|
||||
def test_deployable(self, image_name):
|
||||
if self.builder.configuration.curr_mach.startswith("qemu"):
|
||||
return False
|
||||
deployable = False
|
||||
for t in self.builder.parameters.deployable_image_types:
|
||||
if image_name.endswith(t):
|
||||
@@ -460,13 +373,7 @@ class ImageDetailsPage (HobPage):
|
||||
label = gtk.Label()
|
||||
label.set_use_markup(True)
|
||||
label.set_alignment(0.0, 0.5)
|
||||
label.set_padding(12,0)
|
||||
if primary_action == "Run image":
|
||||
label.set_markup("<span font_desc='12'>Select the image file you want to run:</span>")
|
||||
elif primary_action == "Deploy image":
|
||||
label.set_markup("<span font_desc='12'>Select the image file you want to deploy:</span>")
|
||||
else:
|
||||
label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action)
|
||||
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)
|
||||
@@ -495,12 +402,12 @@ class ImageDetailsPage (HobPage):
|
||||
sel_btn.set_active(fileitem['is_toggled'])
|
||||
sel_btn.connect('toggled', self.table_selected_cb, fileitem)
|
||||
if curr_row < 10:
|
||||
table.attach(sel_btn, 0, 4, curr_row, curr_row + 1, xpadding=24)
|
||||
table.attach(sel_btn, 2, 5, curr_row, curr_row + 1)
|
||||
else:
|
||||
table.attach(sel_btn, 5, 9, curr_row - 10, curr_row - 9, xpadding=24)
|
||||
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)
|
||||
dialog.vbox.pack_start(table, expand=False, fill=False, padding = 6)
|
||||
|
||||
button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
|
||||
HobAltButton.style_button(button)
|
||||
@@ -549,7 +456,7 @@ class ImageDetailsPage (HobPage):
|
||||
name = "Deploy image"
|
||||
if name in buttonlist and self.test_deployable(image_name):
|
||||
deploy_button = HobButton('Deploy image')
|
||||
#deploy_button.set_size_request(205, 49)
|
||||
deploy_button.set_size_request(205, 49)
|
||||
deploy_button.set_tooltip_text("Burn a live image to a USB drive or flash memory")
|
||||
deploy_button.set_flags(gtk.CAN_DEFAULT)
|
||||
button_id = deploy_button.connect("clicked", self.deploy_button_clicked_cb)
|
||||
@@ -562,15 +469,15 @@ class ImageDetailsPage (HobPage):
|
||||
if name in buttonlist and self.test_type_runnable(image_name) and self.test_mach_runnable(image_name):
|
||||
if created == True:
|
||||
# separator
|
||||
#label = gtk.Label(" or ")
|
||||
#self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
label = gtk.Label(" or ")
|
||||
self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
|
||||
# create button "Run image"
|
||||
run_button = HobAltButton("Run image")
|
||||
else:
|
||||
# create button "Run image" as the primary button
|
||||
run_button = HobButton("Run image")
|
||||
#run_button.set_size_request(205, 49)
|
||||
run_button.set_size_request(205, 49)
|
||||
run_button.set_flags(gtk.CAN_DEFAULT)
|
||||
packed = True
|
||||
run_button.set_tooltip_text("Start up an image with qemu emulator")
|
||||
@@ -584,14 +491,14 @@ class ImageDetailsPage (HobPage):
|
||||
if name in buttonlist:
|
||||
if created == True:
|
||||
# separator
|
||||
#label = gtk.Label(" or ")
|
||||
#self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
|
||||
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_size_request(205, 49)
|
||||
save_button.set_flags(gtk.CAN_DEFAULT)
|
||||
packed = True
|
||||
save_button.set_tooltip_text("Save the image configuration for reuse")
|
||||
@@ -608,7 +515,7 @@ class ImageDetailsPage (HobPage):
|
||||
else:
|
||||
build_new_button = HobButton("Build new image")
|
||||
build_new_button.set_flags(gtk.CAN_DEFAULT)
|
||||
#build_new_button.set_size_request(205, 49)
|
||||
build_new_button.set_size_request(205, 49)
|
||||
self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False)
|
||||
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)
|
||||
@@ -658,7 +565,7 @@ class ImageDetailsPage (HobPage):
|
||||
|
||||
def settings_button_clicked_cb(self, button):
|
||||
# Create an advanced settings dialog
|
||||
response, settings_changed = self.builder.show_simple_settings_dialog()
|
||||
response, settings_changed = self.builder.show_adv_settings_dialog()
|
||||
if not response:
|
||||
return
|
||||
if settings_changed:
|
||||
|
||||
@@ -34,19 +34,12 @@ class PackageSelectionPage (HobPage):
|
||||
|
||||
pages = [
|
||||
{
|
||||
'name' : 'Included packages',
|
||||
'tooltip' : 'The packages currently included for your image',
|
||||
'name' : 'Included',
|
||||
'filter' : { PackageListModel.COL_INC : [True] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Package name',
|
||||
'col_id' : PackageListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
@@ -54,24 +47,35 @@ 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,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Size',
|
||||
'col_id' : PackageListModel.COL_SIZE,
|
||||
'col_t_id' : PackageListModel.COL_FONT,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'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
|
||||
}]
|
||||
}, {
|
||||
'name' : 'All packages',
|
||||
'tooltip' : 'All packages that have been built',
|
||||
'filter' : {},
|
||||
'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,
|
||||
@@ -79,6 +83,7 @@ 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,
|
||||
@@ -87,17 +92,15 @@ 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
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
(INCLUDED,
|
||||
ALL) = range(2)
|
||||
|
||||
def __init__(self, builder):
|
||||
super(PackageSelectionPage, self).__init__(builder, "Edit packages")
|
||||
super(PackageSelectionPage, self).__init__(builder, "Packages")
|
||||
|
||||
# set invisiable members
|
||||
self.recipe_model = self.builder.recipe_model
|
||||
@@ -107,7 +110,7 @@ class PackageSelectionPage (HobPage):
|
||||
self.create_visual_elements()
|
||||
|
||||
def included_clicked_cb(self, button):
|
||||
self.ins.set_current_page(self.INCLUDED)
|
||||
self.ins.set_current_page(0)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.label = gtk.Label("Packages included: 0\nSelected packages size: 0 MB")
|
||||
@@ -125,37 +128,35 @@ class PackageSelectionPage (HobPage):
|
||||
filter = page['filter']
|
||||
tab.set_model(self.package_model.tree_model(filter))
|
||||
tab.connect("toggled", self.table_toggled_cb, page['name'])
|
||||
if page['name'] == "Included packages":
|
||||
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'], page['tooltip'])
|
||||
self.ins.append_page(tab, page['name'])
|
||||
self.tables.append(tab)
|
||||
|
||||
self.ins.set_entry("Search packages:")
|
||||
# set the search entry for each table
|
||||
for tab in self.tables:
|
||||
search_tip = "Enter a package name to find it"
|
||||
self.ins.search.set_tooltip_text(search_tip)
|
||||
self.ins.search.props.has_tooltip = True
|
||||
tab.set_search_entry(0, self.ins.search)
|
||||
|
||||
# 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)
|
||||
self.build_image_button.set_size_request(205, 49)
|
||||
self.build_image_button.set_tooltip_text("Build target image")
|
||||
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('Cancel')
|
||||
self.back_button = HobAltButton("<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
self.button_box.pack_end(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()
|
||||
@@ -165,34 +166,11 @@ class PackageSelectionPage (HobPage):
|
||||
if binb:
|
||||
self.builder.show_binb_dialog(binb)
|
||||
|
||||
def open_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 'open log' button if build success
|
||||
self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
|
||||
if log_file:
|
||||
open_log_button = HobAltButton("Open log")
|
||||
open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
|
||||
open_log_button.set_tooltip_text("Open the build's log file")
|
||||
self.button_box.pack_end(open_log_button, expand=False, fill=False)
|
||||
self.button_box.pack_end(self.back_button, expand=False, fill=False)
|
||||
self.show_all()
|
||||
|
||||
def build_image_clicked_cb(self, button):
|
||||
self.builder.build_image()
|
||||
|
||||
def back_button_clicked_cb(self, button):
|
||||
if self.builder.previous_step == self.builder.IMAGE_GENERATED:
|
||||
self.builder.restore_initial_selected_packages()
|
||||
self.refresh_selection()
|
||||
self.builder.show_image_details()
|
||||
else:
|
||||
self.builder.show_configuration()
|
||||
self.builder.show_configuration()
|
||||
|
||||
def _expand_all(self):
|
||||
for tab in self.tables:
|
||||
@@ -218,13 +196,13 @@ class PackageSelectionPage (HobPage):
|
||||
|
||||
self.label.set_label("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 packages", selected_packages_num)
|
||||
self.ins.show_indicator_icon("Included", selected_packages_num)
|
||||
|
||||
def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
|
||||
if not self.package_model.path_included(path):
|
||||
self.package_model.include_item(item_path=path, binb="User Selected")
|
||||
else:
|
||||
if pagename == "Included packages":
|
||||
if pagename == "Included":
|
||||
self.pre_fadeout_checkout_include(view_tree)
|
||||
self.package_model.exclude_item(item_path=path)
|
||||
self.render_fadeout(view_tree, cell)
|
||||
@@ -281,6 +259,19 @@ class PackageSelectionPage (HobPage):
|
||||
tree.set_model(self.package_model.tree_model(self.pages[0]['filter']))
|
||||
tree.expand_all()
|
||||
|
||||
def set_packages_curr_tab(self, curr_page):
|
||||
self.ins.set_current_page(curr_page)
|
||||
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)
|
||||
|
||||
|
||||
@@ -11,9 +11,6 @@ class ProgressBar(gtk.Dialog):
|
||||
self.vbox.pack_start(self.progress)
|
||||
self.show_all()
|
||||
|
||||
def set_text(self, msg):
|
||||
self.progress.set_text(msg)
|
||||
|
||||
def update(self, x, y):
|
||||
self.progress.set_fraction(float(x)/float(y))
|
||||
self.progress.set_text("%2d %%" % (x*100/y))
|
||||
|
||||
@@ -33,10 +33,10 @@ from bb.ui.crumbs.hobpages import HobPage
|
||||
class RecipeSelectionPage (HobPage):
|
||||
pages = [
|
||||
{
|
||||
'name' : 'Included recipes',
|
||||
'name' : 'Included',
|
||||
'tooltip' : 'The recipes currently included for your image',
|
||||
'filter' : { RecipeListModel.COL_INC : [True],
|
||||
RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] },
|
||||
RecipeListModel.COL_TYPE : ['recipe', 'task'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Recipe name',
|
||||
'col_id' : RecipeListModel.COL_NAME,
|
||||
@@ -44,13 +44,6 @@ class RecipeSelectionPage (HobPage):
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Group',
|
||||
'col_id' : RecipeListModel.COL_GROUP,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Brought in by',
|
||||
'col_id' : RecipeListModel.COL_BINB,
|
||||
@@ -58,6 +51,13 @@ class RecipeSelectionPage (HobPage):
|
||||
'col_min' : 100,
|
||||
'col_max' : 500,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Group',
|
||||
'col_id' : RecipeListModel.COL_GROUP,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 300,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
@@ -67,7 +67,7 @@ class RecipeSelectionPage (HobPage):
|
||||
}]
|
||||
}, {
|
||||
'name' : 'All recipes',
|
||||
'tooltip' : 'All recipes in your configured layers',
|
||||
'tooltip' : 'All recipes available in the Yocto Project',
|
||||
'filter' : { RecipeListModel.COL_TYPE : ['recipe'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Recipe name',
|
||||
@@ -76,13 +76,6 @@ class RecipeSelectionPage (HobPage):
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Group',
|
||||
'col_id' : RecipeListModel.COL_GROUP,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'License',
|
||||
'col_id' : RecipeListModel.COL_LIC,
|
||||
@@ -90,6 +83,13 @@ class RecipeSelectionPage (HobPage):
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Group',
|
||||
'col_id' : RecipeListModel.COL_GROUP,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
@@ -98,16 +98,23 @@ class RecipeSelectionPage (HobPage):
|
||||
'col_max' : 100
|
||||
}]
|
||||
}, {
|
||||
'name' : 'Package Groups',
|
||||
'tooltip' : 'All package groups in your configured layers',
|
||||
'filter' : { RecipeListModel.COL_TYPE : ['packagegroup'] },
|
||||
'name' : 'Tasks',
|
||||
'tooltip' : 'All tasks available in the Yocto Project',
|
||||
'filter' : { RecipeListModel.COL_TYPE : ['task'] },
|
||||
'columns' : [{
|
||||
'col_name' : 'Package group name',
|
||||
'col_name' : 'Task name',
|
||||
'col_id' : RecipeListModel.COL_NAME,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Description',
|
||||
'col_id' : RecipeListModel.COL_DESC,
|
||||
'col_style': 'text',
|
||||
'col_min' : 100,
|
||||
'col_max' : 400,
|
||||
'expand' : 'True'
|
||||
}, {
|
||||
'col_name' : 'Included',
|
||||
'col_id' : RecipeListModel.COL_INC,
|
||||
@@ -117,22 +124,18 @@ class RecipeSelectionPage (HobPage):
|
||||
}]
|
||||
}
|
||||
]
|
||||
|
||||
(INCLUDED,
|
||||
ALL,
|
||||
TASKS) = range(3)
|
||||
|
||||
def __init__(self, builder = None):
|
||||
super(RecipeSelectionPage, self).__init__(builder, "Step 1 of 2: Edit recipes")
|
||||
super(RecipeSelectionPage, self).__init__(builder, "Recipes")
|
||||
|
||||
# set invisible members
|
||||
# set invisiable members
|
||||
self.recipe_model = self.builder.recipe_model
|
||||
|
||||
# create visual elements
|
||||
self.create_visual_elements()
|
||||
|
||||
def included_clicked_cb(self, button):
|
||||
self.ins.set_current_page(self.INCLUDED)
|
||||
self.ins.set_current_page(0)
|
||||
|
||||
def create_visual_elements(self):
|
||||
self.eventbox = self.add_onto_top_bar(None, 73)
|
||||
@@ -149,7 +152,7 @@ class RecipeSelectionPage (HobPage):
|
||||
filter = page['filter']
|
||||
tab.set_model(self.recipe_model.tree_model(filter))
|
||||
tab.connect("toggled", self.table_toggled_cb, page['name'])
|
||||
if page['name'] == "Included recipes":
|
||||
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'])
|
||||
@@ -170,16 +173,16 @@ class RecipeSelectionPage (HobPage):
|
||||
self.box_group_area.pack_end(button_box, expand=False, fill=False)
|
||||
|
||||
self.build_packages_button = HobButton('Build packages')
|
||||
#self.build_packages_button.set_size_request(205, 49)
|
||||
self.build_packages_button.set_size_request(205, 49)
|
||||
self.build_packages_button.set_tooltip_text("Build selected recipes into packages")
|
||||
self.build_packages_button.set_flags(gtk.CAN_DEFAULT)
|
||||
self.build_packages_button.grab_default()
|
||||
self.build_packages_button.connect("clicked", self.build_packages_clicked_cb)
|
||||
button_box.pack_end(self.build_packages_button, expand=False, fill=False)
|
||||
|
||||
self.back_button = HobAltButton('Cancel')
|
||||
self.back_button = HobAltButton("<< Back to image configuration")
|
||||
self.back_button.connect("clicked", self.back_button_clicked_cb)
|
||||
button_box.pack_end(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()
|
||||
@@ -198,13 +201,13 @@ 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.ins.show_indicator_icon("Included recipes", 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):
|
||||
if not self.recipe_model.path_included(path):
|
||||
self.recipe_model.include_item(item_path=path, binb="User Selected", image_contents=False)
|
||||
else:
|
||||
if pagename == "Included recipes":
|
||||
if pagename == "Included":
|
||||
self.pre_fadeout_checkout_include(view_tree)
|
||||
self.recipe_model.exclude_item(item_path=path)
|
||||
self.render_fadeout(view_tree, cell)
|
||||
@@ -236,7 +239,7 @@ class RecipeSelectionPage (HobPage):
|
||||
# Check out a model which base on the column COL_FADE_INC,
|
||||
# it's save the prev state of column COL_INC before do exclude_item
|
||||
filter = { RecipeListModel.COL_FADE_INC : [True],
|
||||
RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] }
|
||||
RecipeListModel.COL_TYPE : ['recipe', 'task'] }
|
||||
new_model = self.recipe_model.tree_model(filter, excluded_items_ahead=True)
|
||||
tree.set_model(new_model)
|
||||
|
||||
@@ -258,6 +261,3 @@ class RecipeSelectionPage (HobPage):
|
||||
|
||||
def after_fadeout_checkin_include(self, table, ctrl, cell, tree):
|
||||
tree.set_model(self.recipe_model.tree_model(self.pages[0]['filter']))
|
||||
|
||||
def set_recipe_curr_tab(self, curr_page):
|
||||
self.ins.set_current_page(curr_page)
|
||||
|
||||
@@ -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,34 +337,6 @@ class RunningBuild (gobject.GObject):
|
||||
for reason in event._reasons:
|
||||
msg += ("%s\n" % reason)
|
||||
self.emit("no-provider", msg)
|
||||
self.emit("log", "error", msg)
|
||||
elif isinstance(event, bb.event.LogExecTTY):
|
||||
icon = "dialog-warning"
|
||||
color = HobColors.WARNING
|
||||
if self.sequential or not parent:
|
||||
tree_add = self.model.append
|
||||
else:
|
||||
tree_add = self.model.prepend
|
||||
tree_add(parent,
|
||||
(None,
|
||||
package,
|
||||
task,
|
||||
event.msg,
|
||||
icon,
|
||||
color,
|
||||
0))
|
||||
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
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# BitBake Graphical GTK User Interface
|
||||
#
|
||||
# Copyright (C) 2012 Intel Corporation
|
||||
#
|
||||
# Authored by Bogdan Marinescu <bogdan.a.marinescu@intel.com>
|
||||
#
|
||||
# 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 gtk, gobject
|
||||
from bb.ui.crumbs.progressbar import HobProgressBar
|
||||
from bb.ui.crumbs.hobwidget import hic
|
||||
from bb.ui.crumbs.hobpages import HobPage
|
||||
|
||||
#
|
||||
# SanityCheckPage
|
||||
#
|
||||
class SanityCheckPage (HobPage):
|
||||
|
||||
def __init__(self, builder):
|
||||
super(SanityCheckPage, self).__init__(builder)
|
||||
self.running = False
|
||||
self.create_visual_elements()
|
||||
self.show_all()
|
||||
|
||||
def make_label(self, text, bold=True):
|
||||
label = gtk.Label()
|
||||
label.set_alignment(0.0, 0.5)
|
||||
mark = "<span %s>%s</span>" % (self.span_tag('x-large', 'bold') if bold else self.span_tag('medium'), text)
|
||||
label.set_markup(mark)
|
||||
return label
|
||||
|
||||
def start(self):
|
||||
if not self.running:
|
||||
self.running = True
|
||||
gobject.timeout_add(100, self.timer_func)
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
|
||||
def is_running(self):
|
||||
return self.running
|
||||
|
||||
def timer_func(self):
|
||||
self.progress_bar.pulse()
|
||||
return self.running
|
||||
|
||||
def create_visual_elements(self):
|
||||
# Table'd layout. 'rows' and 'cols' give the table size
|
||||
rows, cols = 30, 50
|
||||
self.table = gtk.Table(rows, cols, True)
|
||||
self.pack_start(self.table, expand=False, fill=False)
|
||||
sx, sy = 2, 2
|
||||
# 'info' icon
|
||||
image = gtk.Image()
|
||||
image.set_from_file(hic.ICON_INFO_DISPLAY_FILE)
|
||||
self.table.attach(image, sx, sx + 2, sy, sy + 3 )
|
||||
image.show()
|
||||
# 'Checking' message
|
||||
label = self.make_label('Hob is checking for correct build system setup')
|
||||
self.table.attach(label, sx + 2, cols, sy, sy + 3, xpadding=5 )
|
||||
label.show()
|
||||
# 'Shouldn't take long' message.
|
||||
label = self.make_label("The check shouldn't take long.", False)
|
||||
self.table.attach(label, sx + 2, cols, sy + 3, sy + 4, xpadding=5)
|
||||
label.show()
|
||||
# Progress bar
|
||||
self.progress_bar = HobProgressBar()
|
||||
self.table.attach(self.progress_bar, sx + 2, cols - 3, sy + 5, sy + 7, xpadding=5)
|
||||
self.progress_bar.show()
|
||||
# All done
|
||||
self.table.show()
|
||||
|
||||
@@ -137,7 +137,7 @@ class RecipeFile(ConfigFile):
|
||||
|
||||
class TemplateMgr(gobject.GObject):
|
||||
|
||||
__gLocalVars__ = ["MACHINE", "PACKAGE_CLASSES", "DISTRO", "DL_DIR", "SSTATE_DIR", "SSTATE_MIRRORS", "PARALLEL_MAKE", "BB_NUMBER_THREADS", "CONF_VERSION"]
|
||||
__gLocalVars__ = ["MACHINE", "PACKAGE_CLASSES", "DISTRO", "DL_DIR", "SSTATE_DIR", "SSTATE_MIRROR", "PARALLEL_MAKE", "BB_NUMBER_THREADS", "CONF_VERSION"]
|
||||
__gBBLayersVars__ = ["BBLAYERS", "LCONF_VERSION"]
|
||||
__gRecipeVars__ = ["DEPENDS", "IMAGE_INSTALL"]
|
||||
|
||||
|
||||
@@ -198,23 +198,17 @@ class gtkthread(threading.Thread):
|
||||
|
||||
def main(server, eventHandler):
|
||||
try:
|
||||
cmdline, error = server.runCommand(["getCmdLineAction"])
|
||||
if error:
|
||||
print("Error getting bitbake commandline: %s" % error)
|
||||
return 1
|
||||
elif not cmdline:
|
||||
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
|
||||
return 1
|
||||
elif not cmdline or cmdline[0] != "generateDotGraph":
|
||||
cmdline = server.runCommand(["getCmdLineAction"])
|
||||
if cmdline and not cmdline['action']:
|
||||
print(cmdline['msg'])
|
||||
return
|
||||
elif not cmdline or (cmdline['action'] and cmdline['action'][0] != "generateDotGraph"):
|
||||
print("This UI is only compatible with the -g option")
|
||||
return 1
|
||||
ret, error = server.runCommand(["generateDepTreeEvent", cmdline[1], cmdline[2]])
|
||||
if error:
|
||||
print("Error running command '%s': %s" % (cmdline, error))
|
||||
return 1
|
||||
elif ret != True:
|
||||
print("Error running command '%s': returned %s" % (cmdline, ret))
|
||||
return 1
|
||||
return
|
||||
ret = server.runCommand(["generateDepTreeEvent", cmdline['action'][1], cmdline['action'][2]])
|
||||
if ret != True:
|
||||
print("Couldn't run command! %s" % ret)
|
||||
return
|
||||
except xmlrpclib.Fault as x:
|
||||
print("XMLRPC Fault getting commandline:\n %s" % x)
|
||||
return
|
||||
@@ -226,8 +220,7 @@ def main(server, eventHandler):
|
||||
|
||||
gtk.gdk.threads_enter()
|
||||
dep = DepExplorer()
|
||||
bardialog = gtk.Dialog(parent=dep,
|
||||
flags=gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT)
|
||||
bardialog = gtk.Dialog(parent=dep)
|
||||
bardialog.set_default_size(400, 50)
|
||||
pbar = HobProgressBar()
|
||||
bardialog.vbox.pack_start(pbar)
|
||||
@@ -240,9 +233,7 @@ def main(server, eventHandler):
|
||||
try:
|
||||
event = eventHandler.waitEvent(0.25)
|
||||
if gtkthread.quit.isSet():
|
||||
_, error = server.runCommand(["stateStop"])
|
||||
if error:
|
||||
print('Unable to cleanly stop: %s' % error)
|
||||
server.runCommand(["stateStop"])
|
||||
break
|
||||
|
||||
if event is None:
|
||||
@@ -318,13 +309,9 @@ def main(server, eventHandler):
|
||||
break
|
||||
if shutdown == 1:
|
||||
print("\nSecond Keyboard Interrupt, stopping...\n")
|
||||
_, error = server.runCommand(["stateStop"])
|
||||
if error:
|
||||
print('Unable to cleanly stop: %s' % error)
|
||||
server.runCommand(["stateStop"])
|
||||
if shutdown == 0:
|
||||
print("\nKeyboard Interrupt, closing down...\n")
|
||||
_, error = server.runCommand(["stateShutdown"])
|
||||
if error:
|
||||
print('Unable to cleanly shutdown: %s' % error)
|
||||
server.runCommand(["stateShutdown"])
|
||||
shutdown = shutdown + 1
|
||||
pass
|
||||
|
||||
@@ -80,19 +80,16 @@ def main (server, eventHandler):
|
||||
running_build.connect ("build-failed", running_build_failed_cb)
|
||||
|
||||
try:
|
||||
cmdline, error = server.runCommand(["getCmdLineAction"])
|
||||
if err:
|
||||
print("Error getting bitbake commandline: %s" % error)
|
||||
return 1
|
||||
elif not cmdline:
|
||||
cmdline = server.runCommand(["getCmdLineAction"])
|
||||
if not cmdline:
|
||||
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
|
||||
return 1
|
||||
ret, error = server.runCommand(cmdline)
|
||||
if error:
|
||||
print("Error running command '%s': %s" % (cmdline, error))
|
||||
elif not cmdline['action']:
|
||||
print(cmdline['msg'])
|
||||
return 1
|
||||
elif ret != True:
|
||||
print("Error running command '%s': returned %s" % (cmdline, ret))
|
||||
ret = server.runCommand(cmdline['action'])
|
||||
if ret != True:
|
||||
print("Couldn't get default commandline! %s" % ret)
|
||||
return 1
|
||||
except xmlrpclib.Fault as x:
|
||||
print("XMLRPC Fault getting commandline:\n %s" % x)
|
||||
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.5 KiB |
@@ -25,12 +25,7 @@ import sys
|
||||
import xmlrpclib
|
||||
import logging
|
||||
import progressbar
|
||||
import signal
|
||||
import bb.msg
|
||||
import time
|
||||
import fcntl
|
||||
import struct
|
||||
import copy
|
||||
from bb.ui import uihelper
|
||||
|
||||
logger = logging.getLogger("BitBake")
|
||||
@@ -42,21 +37,8 @@ class BBProgress(progressbar.ProgressBar):
|
||||
widgets = [progressbar.Percentage(), ' ', progressbar.Bar(), ' ',
|
||||
progressbar.ETA()]
|
||||
|
||||
try:
|
||||
self._resize_default = signal.getsignal(signal.SIGWINCH)
|
||||
except:
|
||||
self._resize_default = None
|
||||
progressbar.ProgressBar.__init__(self, maxval, [self.msg + ": "] + widgets)
|
||||
|
||||
def _handle_resize(self, signum, frame):
|
||||
progressbar.ProgressBar._handle_resize(self, signum, frame)
|
||||
if self._resize_default:
|
||||
self._resize_default(signum, frame)
|
||||
def finish(self):
|
||||
progressbar.ProgressBar.finish(self)
|
||||
if self._resize_default:
|
||||
signal.signal(signal.SIGWINCH, self._resize_default)
|
||||
|
||||
class NonInteractiveProgress(object):
|
||||
fobj = sys.stdout
|
||||
|
||||
@@ -88,152 +70,46 @@ def pluralise(singular, plural, qty):
|
||||
else:
|
||||
return plural % qty
|
||||
|
||||
|
||||
class InteractConsoleLogFilter(logging.Filter):
|
||||
def __init__(self, tf, format):
|
||||
self.tf = tf
|
||||
self.format = format
|
||||
|
||||
def filter(self, record):
|
||||
if record.levelno == self.format.NOTE and (record.msg.startswith("Running") or record.msg.startswith("recipe ")):
|
||||
return False
|
||||
self.tf.clearFooter()
|
||||
return True
|
||||
|
||||
class TerminalFilter(object):
|
||||
columns = 80
|
||||
|
||||
def sigwinch_handle(self, signum, frame):
|
||||
self.columns = self.getTerminalColumns()
|
||||
if self._sigwinch_default:
|
||||
self._sigwinch_default(signum, frame)
|
||||
|
||||
def getTerminalColumns(self):
|
||||
def ioctl_GWINSZ(fd):
|
||||
try:
|
||||
cr = struct.unpack('hh', fcntl.ioctl(fd, self.termios.TIOCGWINSZ, '1234'))
|
||||
except:
|
||||
return None
|
||||
return cr
|
||||
cr = ioctl_GWINSZ(sys.stdout.fileno())
|
||||
if not cr:
|
||||
try:
|
||||
fd = os.open(os.ctermid(), os.O_RDONLY)
|
||||
cr = ioctl_GWINSZ(fd)
|
||||
os.close(fd)
|
||||
except:
|
||||
pass
|
||||
if not cr:
|
||||
try:
|
||||
cr = (env['LINES'], env['COLUMNS'])
|
||||
except:
|
||||
cr = (25, 80)
|
||||
return cr[1]
|
||||
|
||||
def __init__(self, main, helper, console, format):
|
||||
self.main = main
|
||||
self.helper = helper
|
||||
self.cuu = None
|
||||
self.stdinbackup = None
|
||||
self.interactive = sys.stdout.isatty()
|
||||
self.footer_present = False
|
||||
self.lastpids = []
|
||||
|
||||
if not self.interactive:
|
||||
return
|
||||
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
sys.exit("FATAL: The knotty ui could not load the required curses python module.")
|
||||
|
||||
import termios
|
||||
self.curses = curses
|
||||
self.termios = termios
|
||||
try:
|
||||
fd = sys.stdin.fileno()
|
||||
self.stdinbackup = termios.tcgetattr(fd)
|
||||
new = copy.deepcopy(self.stdinbackup)
|
||||
new[3] = new[3] & ~termios.ECHO
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, new)
|
||||
curses.setupterm()
|
||||
self.ed = curses.tigetstr("ed")
|
||||
if self.ed:
|
||||
self.cuu = curses.tigetstr("cuu")
|
||||
try:
|
||||
self._sigwinch_default = signal.getsignal(signal.SIGWINCH)
|
||||
signal.signal(signal.SIGWINCH, self.sigwinch_handle)
|
||||
except:
|
||||
pass
|
||||
self.columns = self.getTerminalColumns()
|
||||
except:
|
||||
self.cuu = None
|
||||
console.addFilter(InteractConsoleLogFilter(self, format))
|
||||
|
||||
def clearFooter(self):
|
||||
if self.footer_present:
|
||||
lines = self.footer_present
|
||||
sys.stdout.write(self.curses.tparm(self.cuu, lines))
|
||||
sys.stdout.write(self.curses.tparm(self.ed))
|
||||
self.footer_present = False
|
||||
return
|
||||
|
||||
def updateFooter(self):
|
||||
if not self.cuu:
|
||||
if not main.shutdown or not self.helper.needUpdate:
|
||||
return
|
||||
|
||||
activetasks = self.helper.running_tasks
|
||||
failedtasks = self.helper.failed_tasks
|
||||
runningpids = self.helper.running_pids
|
||||
if self.footer_present and (self.lastcount == self.helper.tasknumber_current) and (self.lastpids == runningpids):
|
||||
return
|
||||
if self.footer_present:
|
||||
self.clearFooter()
|
||||
if not self.helper.tasknumber_total or self.helper.tasknumber_current == self.helper.tasknumber_total:
|
||||
|
||||
if len(runningpids) == 0:
|
||||
return
|
||||
|
||||
self.helper.getTasks()
|
||||
|
||||
tasks = []
|
||||
for t in runningpids:
|
||||
tasks.append("%s (pid %s)" % (activetasks[t]["title"], t))
|
||||
|
||||
if self.main.shutdown:
|
||||
content = "Waiting for %s running tasks to finish:" % len(activetasks)
|
||||
elif not len(activetasks):
|
||||
content = "No currently running tasks (%s of %s)" % (self.helper.tasknumber_current, self.helper.tasknumber_total)
|
||||
if main.shutdown:
|
||||
print("Waiting for %s running tasks to finish:" % len(activetasks))
|
||||
else:
|
||||
content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
|
||||
print content
|
||||
lines = 1 + int(len(content) / (self.columns + 1))
|
||||
print("Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total))
|
||||
for tasknum, task in enumerate(tasks):
|
||||
content = "%s: %s" % (tasknum, task)
|
||||
print content
|
||||
lines = lines + 1 + int(len(content) / (self.columns + 1))
|
||||
self.footer_present = lines
|
||||
self.lastpids = runningpids[:]
|
||||
self.lastcount = self.helper.tasknumber_current
|
||||
print("%s: %s" % (tasknum, task))
|
||||
|
||||
def finish(self):
|
||||
if self.stdinbackup:
|
||||
fd = sys.stdin.fileno()
|
||||
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
|
||||
return
|
||||
|
||||
def main(server, eventHandler, tf = TerminalFilter):
|
||||
|
||||
# Get values of variables which control our output
|
||||
includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
|
||||
if error:
|
||||
logger.error("Unable to get the value of BBINCLUDELOGS variable: %s" % error)
|
||||
return 1
|
||||
loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
|
||||
if error:
|
||||
logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s" % error)
|
||||
return 1
|
||||
consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
|
||||
if error:
|
||||
logger.error("Unable to get the value of BB_CONSOLELOG variable: %s" % error)
|
||||
return 1
|
||||
|
||||
if sys.stdin.isatty() and sys.stdout.isatty():
|
||||
log_exec_tty = True
|
||||
else:
|
||||
log_exec_tty = False
|
||||
includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"])
|
||||
loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
|
||||
consolelogfile = server.runCommand(["getVariable", "BB_CONSOLELOG"])
|
||||
|
||||
helper = uihelper.BBUIHelper()
|
||||
|
||||
@@ -243,29 +119,25 @@ 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)
|
||||
logger.addHandler(consolelog)
|
||||
|
||||
try:
|
||||
cmdline, error = server.runCommand(["getCmdLineAction"])
|
||||
if error:
|
||||
logger.error("Unable to get bitbake commandline arguments: %s" % error)
|
||||
return 1
|
||||
elif not cmdline:
|
||||
cmdline = server.runCommand(["getCmdLineAction"])
|
||||
if not cmdline:
|
||||
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
|
||||
return 1
|
||||
ret, error = server.runCommand(cmdline)
|
||||
if error:
|
||||
logger.error("Command '%s' failed: %s" % (cmdline, error))
|
||||
elif not cmdline['action']:
|
||||
print(cmdline['msg'])
|
||||
return 1
|
||||
elif ret != True:
|
||||
logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
|
||||
ret = server.runCommand(cmdline['action'])
|
||||
if ret != True:
|
||||
print("Couldn't get default commandline! %s" % ret)
|
||||
return 1
|
||||
except xmlrpclib.Fault as x:
|
||||
logger.error("XMLRPC Fault getting commandline:\n %s" % x)
|
||||
print("XMLRPC Fault getting commandline:\n %s" % x)
|
||||
return 1
|
||||
|
||||
parseprogress = None
|
||||
@@ -292,20 +164,6 @@ def main(server, eventHandler, tf = TerminalFilter):
|
||||
if not main.shutdown:
|
||||
main.shutdown = 1
|
||||
|
||||
if isinstance(event, bb.event.LogExecTTY):
|
||||
if log_exec_tty:
|
||||
tries = event.retries
|
||||
while tries:
|
||||
print "Trying to run: %s" % event.prog
|
||||
if os.system(event.prog) == 0:
|
||||
break
|
||||
time.sleep(event.sleep_delay)
|
||||
tries -= 1
|
||||
if tries:
|
||||
continue
|
||||
logger.warn(event.msg)
|
||||
continue
|
||||
|
||||
if isinstance(event, logging.LogRecord):
|
||||
if event.levelno >= format.ERROR:
|
||||
errors = errors + 1
|
||||
@@ -449,8 +307,7 @@ def main(server, eventHandler, tf = TerminalFilter):
|
||||
bb.runqueue.runQueueExitWait,
|
||||
bb.event.OperationStarted,
|
||||
bb.event.OperationCompleted,
|
||||
bb.event.OperationProgress,
|
||||
bb.event.DiskFull)):
|
||||
bb.event.OperationProgress)):
|
||||
continue
|
||||
|
||||
logger.error("Unknown event: %s", event)
|
||||
@@ -461,19 +318,14 @@ def main(server, eventHandler, tf = TerminalFilter):
|
||||
if ioerror.args[0] == 4:
|
||||
pass
|
||||
except KeyboardInterrupt:
|
||||
import time
|
||||
termfilter.clearFooter()
|
||||
if main.shutdown == 1:
|
||||
print("\nSecond Keyboard Interrupt, stopping...\n")
|
||||
_, error = server.runCommand(["stateStop"])
|
||||
if error:
|
||||
logger.error("Unable to cleanly stop: %s" % error)
|
||||
server.runCommand(["stateStop"])
|
||||
if main.shutdown == 0:
|
||||
print("\nKeyboard Interrupt, closing down...\n")
|
||||
interrupted = True
|
||||
_, error = server.runCommand(["stateShutdown"])
|
||||
if error:
|
||||
logger.error("Unable to cleanly shutdown: %s" % error)
|
||||
print("\nKeyboard Interrupt, closing down...\n")
|
||||
server.runCommand(["stateShutdown"])
|
||||
main.shutdown = main.shutdown + 1
|
||||
pass
|
||||
|
||||
|
||||
109
bitbake/lib/bb/ui/knotty2.py
Normal file
@@ -0,0 +1,109 @@
|
||||
#
|
||||
# BitBake (No)TTY UI Implementation (v2)
|
||||
#
|
||||
# Handling output to TTYs or files (no TTY)
|
||||
#
|
||||
# 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.
|
||||
|
||||
from bb.ui import knotty
|
||||
import logging
|
||||
import sys
|
||||
logger = logging.getLogger("BitBake")
|
||||
|
||||
class InteractConsoleLogFilter(logging.Filter):
|
||||
def __init__(self, tf, format):
|
||||
self.tf = tf
|
||||
self.format = format
|
||||
|
||||
def filter(self, record):
|
||||
if record.levelno == self.format.NOTE and (record.msg.startswith("Running") or record.msg.startswith("package ")):
|
||||
return False
|
||||
self.tf.clearFooter()
|
||||
return True
|
||||
|
||||
class TerminalFilter2(object):
|
||||
def __init__(self, main, helper, console, format):
|
||||
self.main = main
|
||||
self.helper = helper
|
||||
self.cuu = None
|
||||
self.stdinbackup = None
|
||||
self.interactive = sys.stdout.isatty()
|
||||
self.footer_present = False
|
||||
self.lastpids = []
|
||||
|
||||
if not self.interactive:
|
||||
return
|
||||
|
||||
import curses
|
||||
import termios
|
||||
import copy
|
||||
self.curses = curses
|
||||
self.termios = termios
|
||||
try:
|
||||
fd = sys.stdin.fileno()
|
||||
self.stdinbackup = termios.tcgetattr(fd)
|
||||
new = copy.deepcopy(self.stdinbackup)
|
||||
new[3] = new[3] & ~termios.ECHO
|
||||
termios.tcsetattr(fd, termios.TCSADRAIN, new)
|
||||
curses.setupterm()
|
||||
self.ed = curses.tigetstr("ed")
|
||||
if self.ed:
|
||||
self.cuu = curses.tigetstr("cuu")
|
||||
except:
|
||||
self.cuu = None
|
||||
console.addFilter(InteractConsoleLogFilter(self, format))
|
||||
|
||||
def clearFooter(self):
|
||||
if self.footer_present:
|
||||
lines = self.footer_present
|
||||
sys.stdout.write(self.curses.tparm(self.cuu, lines))
|
||||
sys.stdout.write(self.curses.tparm(self.ed))
|
||||
self.footer_present = False
|
||||
|
||||
def updateFooter(self):
|
||||
if not self.cuu:
|
||||
return
|
||||
activetasks = self.helper.running_tasks
|
||||
failedtasks = self.helper.failed_tasks
|
||||
runningpids = self.helper.running_pids
|
||||
if self.footer_present and (self.lastpids == runningpids):
|
||||
return
|
||||
if self.footer_present:
|
||||
self.clearFooter()
|
||||
if not activetasks:
|
||||
return
|
||||
lines = 1
|
||||
tasks = []
|
||||
for t in runningpids:
|
||||
tasks.append("%s (pid %s)" % (activetasks[t]["title"], t))
|
||||
|
||||
if self.main.shutdown:
|
||||
print("Waiting for %s running tasks to finish:" % len(activetasks))
|
||||
else:
|
||||
print("Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total))
|
||||
for tasknum, task in enumerate(tasks):
|
||||
print("%s: %s" % (tasknum, task))
|
||||
lines = lines + 1
|
||||
self.footer_present = lines
|
||||
self.lastpids = runningpids[:]
|
||||
|
||||
def finish(self):
|
||||
if self.stdinbackup:
|
||||
fd = sys.stdin.fileno()
|
||||
self.termios.tcsetattr(fd, self.termios.TCSADRAIN, self.stdinbackup)
|
||||
|
||||
def main(server, eventHandler):
|
||||
return bb.ui.knotty.main(server, eventHandler, TerminalFilter2)
|
||||
@@ -47,13 +47,7 @@
|
||||
|
||||
from __future__ import division
|
||||
import logging
|
||||
import os, sys, itertools, time, subprocess
|
||||
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
sys.exit("FATAL: The ncurses ui could not load the required curses python module.")
|
||||
|
||||
import os, sys, curses, itertools, time, subprocess
|
||||
import bb
|
||||
import xmlrpclib
|
||||
from bb import ui
|
||||
@@ -236,18 +230,15 @@ class NCursesUI:
|
||||
shutdown = 0
|
||||
|
||||
try:
|
||||
cmdline, error = server.runCommand(["getCmdLineAction"])
|
||||
cmdline = server.runCommand(["getCmdLineAction"])
|
||||
if not cmdline:
|
||||
print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
|
||||
return
|
||||
elif error:
|
||||
print("Error getting bitbake commandline: %s" % error)
|
||||
elif not cmdline['action']:
|
||||
print(cmdline['msg'])
|
||||
return
|
||||
ret, error = server.runCommand(cmdline)
|
||||
if error:
|
||||
print("Error running command '%s': %s" % (cmdline, error))
|
||||
return
|
||||
elif ret != True:
|
||||
ret = server.runCommand(cmdline['action'])
|
||||
if ret != True:
|
||||
print("Couldn't get default commandlind! %s" % ret)
|
||||
return
|
||||
except xmlrpclib.Fault as x:
|
||||
@@ -321,8 +312,6 @@ class NCursesUI:
|
||||
if isinstance(event, bb.cooker.CookerExit):
|
||||
exitflag = True
|
||||
|
||||
if isinstance(event, bb.event.LogExecTTY):
|
||||
mw.appendText('WARN: ' + event.msg + '\n')
|
||||
if helper.needUpdate:
|
||||
activetasks, failedtasks = helper.getTasks()
|
||||
taw.erase()
|
||||
@@ -348,14 +337,10 @@ class NCursesUI:
|
||||
exitflag = True
|
||||
if shutdown == 1:
|
||||
mw.appendText("Second Keyboard Interrupt, stopping...\n")
|
||||
_, error = server.runCommand(["stateStop"])
|
||||
if error:
|
||||
print("Unable to cleanly stop: %s" % error)
|
||||
server.runCommand(["stateStop"])
|
||||
if shutdown == 0:
|
||||
mw.appendText("Keyboard Interrupt, closing down...\n")
|
||||
_, error = server.runCommand(["stateShutdown"])
|
||||
if error:
|
||||
print("Unable to cleanly shutdown: %s" % error)
|
||||
server.runCommand(["stateShutdown"])
|
||||
shutdown = shutdown + 1
|
||||
pass
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ class BBUIHelper:
|
||||
self.running_pids.remove(event.pid)
|
||||
self.failed_tasks.append( { 'title' : "%s %s" % (event._package, event._task)})
|
||||
self.needUpdate = True
|
||||
if isinstance(event, bb.runqueue.runQueueTaskStarted) or isinstance(event, bb.runqueue.sceneQueueTaskStarted):
|
||||
if isinstance(event, bb.runqueue.runQueueTaskStarted):
|
||||
self.tasknumber_current = event.stats.completed + event.stats.active + event.stats.failed + 1
|
||||
self.tasknumber_total = event.stats.total
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ def explode_deps(s):
|
||||
#r[-1] += ' ' + ' '.join(j)
|
||||
return r
|
||||
|
||||
def explode_dep_versions2(s):
|
||||
def explode_dep_versions(s):
|
||||
"""
|
||||
Take an RDEPENDS style string of format:
|
||||
"DEPEND1 (optional version) DEPEND2 (optional version) ..."
|
||||
@@ -147,70 +147,24 @@ def explode_dep_versions2(s):
|
||||
r = {}
|
||||
l = s.replace(",", "").split()
|
||||
lastdep = None
|
||||
lastcmp = ""
|
||||
lastver = ""
|
||||
incmp = False
|
||||
inversion = False
|
||||
for i in l:
|
||||
if i[0] == '(':
|
||||
incmp = True
|
||||
i = i[1:].strip()
|
||||
if not i:
|
||||
continue
|
||||
|
||||
if incmp:
|
||||
incmp = False
|
||||
inversion = True
|
||||
# This list is based on behavior and supported comparisons from deb, opkg and rpm.
|
||||
#
|
||||
# Even though =<, <<, ==, !=, =>, and >> may not be supported,
|
||||
# we list each possibly valid item.
|
||||
# The build system is responsible for validation of what it supports.
|
||||
if i.startswith(('<=', '=<', '<<', '==', '!=', '>=', '=>', '>>')):
|
||||
lastcmp = i[0:2]
|
||||
i = i[2:]
|
||||
elif i.startswith(('<', '>', '=')):
|
||||
lastcmp = i[0:1]
|
||||
i = i[1:]
|
||||
else:
|
||||
# This is an unsupported case!
|
||||
lastcmp = (i or "")
|
||||
i = ""
|
||||
i.strip()
|
||||
if not i:
|
||||
continue
|
||||
lastver = i[1:] or ""
|
||||
#j = []
|
||||
elif inversion and i.endswith(')'):
|
||||
inversion = False
|
||||
lastver = lastver + " " + (i[:-1] or "")
|
||||
r[lastdep] = lastver
|
||||
elif not inversion:
|
||||
r[i] = None
|
||||
lastdep = i
|
||||
lastver = ""
|
||||
elif inversion:
|
||||
lastver = lastver + " " + i
|
||||
|
||||
if inversion:
|
||||
if i.endswith(')'):
|
||||
i = i[:-1] or ""
|
||||
inversion = False
|
||||
if lastver and i:
|
||||
lastver += " "
|
||||
if i:
|
||||
lastver += i
|
||||
if lastdep not in r:
|
||||
r[lastdep] = []
|
||||
r[lastdep].append(lastcmp + " " + lastver)
|
||||
continue
|
||||
|
||||
#if not inversion:
|
||||
lastdep = i
|
||||
lastver = ""
|
||||
lastcmp = ""
|
||||
if not (i in r and r[i]):
|
||||
r[lastdep] = []
|
||||
|
||||
return r
|
||||
|
||||
def explode_dep_versions(s):
|
||||
r = explode_dep_versions2(s)
|
||||
for d in r:
|
||||
if not r[d]:
|
||||
r[d] = None
|
||||
continue
|
||||
if len(r[d]) > 1:
|
||||
bb.warn("explode_dep_versions(): Item %s appeared in dependency string '%s' multiple times with different values. explode_dep_versions cannot cope with this." % (d, s))
|
||||
r[d] = r[d][0]
|
||||
return r
|
||||
|
||||
def join_deps(deps, commasep=True):
|
||||
@@ -220,11 +174,7 @@ def join_deps(deps, commasep=True):
|
||||
result = []
|
||||
for dep in deps:
|
||||
if deps[dep]:
|
||||
if isinstance(deps[dep], list):
|
||||
for v in deps[dep]:
|
||||
result.append(dep + " (" + v + ")")
|
||||
else:
|
||||
result.append(dep + " (" + deps[dep] + ")")
|
||||
result.append(dep + " (" + deps[dep] + ")")
|
||||
else:
|
||||
result.append(dep)
|
||||
if commasep:
|
||||
@@ -266,23 +216,20 @@ def better_compile(text, file, realfile, mode = "exec"):
|
||||
for line in body:
|
||||
logger.error(line)
|
||||
|
||||
e = bb.BBHandledException(e)
|
||||
raise e
|
||||
raise
|
||||
|
||||
def better_exec(code, context, text = None, realfile = "<code>"):
|
||||
def better_exec(code, context, text, realfile = "<code>"):
|
||||
"""
|
||||
Similiar to better_compile, better_exec will
|
||||
print the lines that are responsible for the
|
||||
error.
|
||||
"""
|
||||
import bb.parse
|
||||
if not text:
|
||||
text = code
|
||||
if not hasattr(code, "co_filename"):
|
||||
code = better_compile(code, realfile, realfile)
|
||||
try:
|
||||
exec(code, _context, context)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
(t, value, tb) = sys.exc_info()
|
||||
|
||||
if t in [bb.parse.SkipPackage, bb.build.FuncFailed]:
|
||||
@@ -307,32 +254,22 @@ def better_exec(code, context, text = None, realfile = "<code>"):
|
||||
|
||||
logger.error("The code that was being executed was:")
|
||||
_print_trace(textarray, linefailed)
|
||||
logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[0][0], tbextract[0][1], tbextract[0][2])
|
||||
logger.error("(file: '%s', lineno: %s, function: %s)", tbextract[0][0], tbextract[0][1], tbextract[0][2])
|
||||
|
||||
# See if this is a function we constructed and has calls back into other functions in
|
||||
# "text". If so, try and improve the context of the error by diving down the trace
|
||||
level = 0
|
||||
nexttb = tb.tb_next
|
||||
while nexttb is not None and (level+1) < len(tbextract):
|
||||
while nexttb is not None:
|
||||
if tbextract[level][0] == tbextract[level+1][0] and tbextract[level+1][2] == tbextract[level][0]:
|
||||
_print_trace(textarray, tbextract[level+1][1])
|
||||
logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2])
|
||||
elif "d" in context and tbextract[level+1][2]:
|
||||
d = context["d"]
|
||||
functionname = tbextract[level+1][2]
|
||||
text = d.getVar(functionname, True)
|
||||
if text:
|
||||
_print_trace(text.split('\n'), tbextract[level+1][1])
|
||||
logger.error("[From file: '%s', lineno: %s, function: %s]", tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2])
|
||||
else:
|
||||
break
|
||||
logger.error("(file: '%s', lineno: %s, function: %s)", tbextract[level+1][0], tbextract[level+1][1], tbextract[level+1][2])
|
||||
else:
|
||||
break
|
||||
nexttb = tb.tb_next
|
||||
level = level + 1
|
||||
|
||||
e = bb.BBHandledException(e)
|
||||
raise e
|
||||
raise
|
||||
|
||||
def simple_exec(code, context):
|
||||
exec(code, _context, context)
|
||||
|
||||
@@ -266,20 +266,17 @@ def is_local_special(host, port):
|
||||
else:
|
||||
return False
|
||||
|
||||
class PRServiceConfigError(Exception):
|
||||
pass
|
||||
|
||||
def auto_start(d):
|
||||
global singleton
|
||||
if (not d.getVar('PRSERV_HOST', True)) or (not d.getVar('PRSERV_PORT', True)):
|
||||
return
|
||||
return True
|
||||
|
||||
if is_local_special(d.getVar('PRSERV_HOST', True), int(d.getVar('PRSERV_PORT', True))) and not singleton:
|
||||
import bb.utils
|
||||
cachedir = (d.getVar("PERSISTENT_DIR", True) or d.getVar("CACHE", True))
|
||||
if not cachedir:
|
||||
logger.critical("Please set the 'PERSISTENT_DIR' or 'CACHE' variable")
|
||||
raise PRServiceConfigError
|
||||
sys.exit(1)
|
||||
bb.utils.mkdirhier(cachedir)
|
||||
dbfile = os.path.join(cachedir, "prserv.sqlite3")
|
||||
logfile = os.path.join(cachedir, "prserv.log")
|
||||
@@ -295,7 +292,7 @@ def auto_start(d):
|
||||
return PRServerConnection(host,port).ping()
|
||||
except Exception:
|
||||
logger.critical("PRservice %s:%d not available" % (host, port))
|
||||
raise PRServiceConfigError
|
||||
return False
|
||||
|
||||
def auto_shutdown(d=None):
|
||||
global singleton
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
# This is a single Makefile to handle all generated Yocto Project documents.
|
||||
# The Makefile needs to live in the documents directory and all figures used
|
||||
# in any manuals must be .PNG files and live in the individual book's figures
|
||||
# directory as well as in the figures directory for the mega-manual.
|
||||
# Note that the figures for the Yocto Project Development Manual
|
||||
# differ depending on the BRANCH being built.
|
||||
# directory. Note that the figures for the Yocto Project Development Manual
|
||||
# differ between the 'master' and 'edison' branches.
|
||||
#
|
||||
# The Makefile has these targets:
|
||||
#
|
||||
# pdf: generates a PDF version of a manual. Not valid for the Quick Start
|
||||
# or the mega-manual (single, large HTML file comprised of all
|
||||
# Yocto Project manuals).
|
||||
# html: generates an HTML version of a manual.
|
||||
# tarball: creates a tarball for the doc files.
|
||||
# validate: validates
|
||||
@@ -17,22 +14,18 @@
|
||||
# clean: removes files
|
||||
#
|
||||
# The Makefile generates an HTML and PDF version of every document except the
|
||||
# Yocto Project Quick Start and the single, HTML mega-manual, which is comprised
|
||||
# of all the individual Yocto Project manuals. These two manuals are in HTML
|
||||
# form only. The variable DOC indicates the folder name for a given manual. The
|
||||
# variable VER represents the distro version of the Yocto Release for which the
|
||||
# manuals are being generated. The variable BRANCH is used to indicate the
|
||||
# branch (edison or denzil) and is used only when DOC=dev-manual or
|
||||
# DOC=mega-manual. If you do not specify a BRANCH, the default branch used
|
||||
# will be for the latest Yocto Project release. If you build for either
|
||||
# edison or denzil, you must use BRANCH. You do not need to use BRANCH for
|
||||
# any release beyond denzil.
|
||||
# Yocto Project Quick Start. The Quick Start is in HTML form only. The variable
|
||||
# DOC is used to indicate the folder name for a given manual. The variable
|
||||
# VER represents the distro version of the Yocto Release for which the manuals
|
||||
# are being generated. The variable BRANCH is used to indicate the 'edison'
|
||||
# branch and is used only when DOC=dev-manual (making the YP Development
|
||||
# Manual).
|
||||
#
|
||||
# To build a manual, you must invoke Makefile with the DOC argument. If you
|
||||
# are going to publish the manual, then you must invoke Makefile with both the
|
||||
# DOC and the VER argument. Furthermore, if you are building or publishing
|
||||
# the edison or denzil versions of the Yocto Poject Development Manual or
|
||||
# the mega-manual, you must also use the BRANCH argument.
|
||||
# To build the HTML and PDF versions of the manual you must invoke the Makefile
|
||||
# with the DOC argument. If you are going to publish the manual then you
|
||||
# you must invoke the Makefile with both the DOC and the VER argument.
|
||||
# If you are building the 'edison' version of the YP DEvelopment Manual then
|
||||
# you must use the DOC and BRANCH arguments.
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
@@ -40,43 +33,39 @@
|
||||
# make DOC=yocto-project-qs
|
||||
# make pdf DOC=poky-ref-manual
|
||||
# make DOC=dev-manual BRANCH=edison
|
||||
# make DOC=mega-manual BRANCH=denzil
|
||||
#
|
||||
# The first example generates the HTML and PDF versions of the BSP Guide.
|
||||
# The second example generates the HTML version only of the Quick Start. Note that
|
||||
# the Quick Start only has an HTML version available. The third example generates
|
||||
# both the PDF and HTML versions of the Yocto Project Reference Manual. The
|
||||
# fourth example generates both the PDF and HTML 'edison' versions of the YP
|
||||
# Development Manual. The last exmample generates the HTML version of the
|
||||
# mega-manual and uses the 'denzil' branch when choosing figures for the
|
||||
# tarball of figures. Any example that does not use the BRANCH argument
|
||||
# builds the current version of the manual set.
|
||||
# last example generates both the PDF and HTML 'edison' versions of the YP
|
||||
# Development Manual.
|
||||
#
|
||||
# Use the publish target to push the generated manuals to the Yocto Project
|
||||
# website. All files needed for the manual's HTML form are pushed as well as the
|
||||
# PDF version (if applicable).
|
||||
# Examples:
|
||||
#
|
||||
# make publish DOC=bsp-guide VER=1.3
|
||||
# make publish DOC=adt-manual VER=1.3
|
||||
# make publish DOC=bsp-guide VER=1.2
|
||||
# make publish DOC=adt-manual VER=1.2
|
||||
# make publish DOC=dev-manual VER=1.1.1 BRANCH=edison
|
||||
# make publish DOC=dev-manual VER=1.2 BRANCH=denzil
|
||||
# make publish DOC=dev-manual VER=1.2
|
||||
#
|
||||
# The first example publishes the 1.3 version of both the PDF and HTML versions of
|
||||
# the BSP Guide. The second example publishes the 1.3 version of both the PDF and
|
||||
# The first example publishes the 1.2 version of both the PDF and HTML versions of
|
||||
# the BSP Guide. The second example publishes the 1.2 version of both the PDF and
|
||||
# HTML versions of the ADT Manual. The third example publishes the PDF and HTML
|
||||
# 'edison' versions of the YP Development Manual. The fourth example publishes
|
||||
# the PDF and HTML 'denzil' versions of the YP Development Manual.
|
||||
# 'edison' versions of the YP Development Manual. Finally, the last example publishes
|
||||
# the PDF and HTML 'master' versions of the YP Development Manual.
|
||||
#
|
||||
|
||||
ifeq ($(DOC),bsp-guide)
|
||||
XSLTOPTS = --stringparam html.stylesheet bsp-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html pdf tarball
|
||||
TARFILES = bsp-style.css bsp-guide.html bsp-guide.pdf figures/bsp-title.png
|
||||
TARFILES = style.css bsp-guide.html bsp-guide.pdf figures/bsp-title.png
|
||||
MANUALS = $(DOC)/$(DOC).html $(DOC)/$(DOC).pdf
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
@@ -84,7 +73,7 @@ STYLESHEET = $(DOC)/*.css
|
||||
endif
|
||||
|
||||
ifeq ($(DOC),dev-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet dev-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
@@ -98,7 +87,7 @@ ALLPREQ = html pdf tarball
|
||||
#
|
||||
|
||||
ifeq ($(BRANCH),edison)
|
||||
TARFILES = dev-style.css dev-manual.html dev-manual.pdf \
|
||||
TARFILES = style.css dev-manual.html dev-manual.pdf \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-example-repos-edison.png \
|
||||
@@ -107,7 +96,7 @@ TARFILES = dev-style.css dev-manual.html dev-manual.pdf \
|
||||
figures/source-repos.png figures/yp-download.png \
|
||||
figures/wip.png
|
||||
else ifeq ($(BRANCH),denzil)
|
||||
TARFILES = dev-style.css dev-manual.html dev-manual.pdf \
|
||||
TARFILES = style.css dev-manual.html dev-manual.pdf \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-example-repos-denzil.png \
|
||||
@@ -116,11 +105,14 @@ TARFILES = dev-style.css dev-manual.html dev-manual.pdf \
|
||||
figures/source-repos.png figures/yp-download.png \
|
||||
figures/wip.png
|
||||
else
|
||||
TARFILES = dev-style.css dev-manual.html dev-manual.pdf \
|
||||
TARFILES = style.css dev-manual.html dev-manual.pdf \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-overview-1.png figures/kernel-overview-2-generic.png \
|
||||
figures/source-repos.png figures/yp-download.png
|
||||
figures/kernel-example-repos-denzil.png \
|
||||
figures/kernel-overview-1.png figures/kernel-overview-2.png \
|
||||
figures/kernel-overview-3-denzil.png \
|
||||
figures/source-repos.png figures/yp-download.png \
|
||||
figures/wip.png
|
||||
endif
|
||||
|
||||
MANUALS = $(DOC)/$(DOC).html $(DOC)/$(DOC).pdf
|
||||
@@ -130,76 +122,24 @@ STYLESHEET = $(DOC)/*.css
|
||||
endif
|
||||
|
||||
ifeq ($(DOC),yocto-project-qs)
|
||||
XSLTOPTS = --stringparam html.stylesheet qs-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--xinclude
|
||||
ALLPREQ = html tarball
|
||||
TARFILES = yocto-project-qs.html qs-style.css figures/yocto-environment.png figures/building-an-image.png figures/using-a-pre-built-image.png figures/yocto-project-transp.png
|
||||
TARFILES = yocto-project-qs.html style.css figures/yocto-environment.png figures/building-an-image.png figures/using-a-pre-built-image.png figures/yocto-project-transp.png
|
||||
MANUALS = $(DOC)/$(DOC).html
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
endif
|
||||
|
||||
ifeq ($(DOC),mega-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet mega-style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html tarball
|
||||
|
||||
ifeq ($(BRANCH),edison)
|
||||
TARFILES = mega-manual.html mega-style.css figures/yocto-environment.png figures/building-an-image.png \
|
||||
figures/using-a-pre-built-image.png \
|
||||
figures/poky-title.png \
|
||||
figures/adt-title.png figures/bsp-title.png \
|
||||
figures/kernel-title.png figures/kernel-architecture-overview.png \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-example-repos-edison.png \
|
||||
figures/kernel-overview-1.png figures/kernel-overview-2.png \
|
||||
figures/kernel-overview-3-edison.png \
|
||||
figures/source-repos.png figures/yp-download.png \
|
||||
figures/wip.png
|
||||
else ifeq ($(BRANCH),denzil)
|
||||
TARFILES = mega-manual.html mega-style.css figures/yocto-environment.png figures/building-an-image.png \
|
||||
figures/using-a-pre-built-image.png \
|
||||
figures/poky-title.png \
|
||||
figures/adt-title.png figures/bsp-title.png \
|
||||
figures/kernel-title.png figures/kernel-architecture-overview.png \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-example-repos-denzil.png \
|
||||
figures/kernel-overview-1.png figures/kernel-overview-2.png \
|
||||
figures/kernel-overview-3-denzil.png \
|
||||
figures/source-repos.png figures/yp-download.png \
|
||||
figures/wip.png
|
||||
else
|
||||
TARFILES = mega-manual.html mega-style.css figures/yocto-environment.png figures/building-an-image.png \
|
||||
figures/using-a-pre-built-image.png \
|
||||
figures/poky-title.png \
|
||||
figures/adt-title.png figures/bsp-title.png \
|
||||
figures/kernel-title.png figures/kernel-architecture-overview.png \
|
||||
figures/app-dev-flow.png figures/bsp-dev-flow.png figures/dev-title.png \
|
||||
figures/git-workflow.png figures/index-downloads.png figures/kernel-dev-flow.png \
|
||||
figures/kernel-overview-1.png figures/kernel-overview-2-generic.png \
|
||||
figures/source-repos.png figures/yp-download.png
|
||||
endif
|
||||
|
||||
MANUALS = $(DOC)/$(DOC).html
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(DOC),poky-ref-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet ref-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam appendix.autolabel A \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html pdf tarball
|
||||
TARFILES = poky-ref-manual.html ref-style.css figures/poky-title.png
|
||||
TARFILES = poky-ref-manual.html style.css figures/poky-title.png
|
||||
MANUALS = $(DOC)/$(DOC).html $(DOC)/$(DOC).pdf
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
@@ -207,28 +147,28 @@ endif
|
||||
|
||||
|
||||
ifeq ($(DOC),adt-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet adt-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam appendix.autolabel A \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html pdf tarball
|
||||
TARFILES = adt-manual.html adt-manual.pdf adt-style.css figures/adt-title.png
|
||||
TARFILES = adt-manual.html adt-manual.pdf style.css figures/adt-title.png
|
||||
MANUALS = $(DOC)/$(DOC).html $(DOC)/$(DOC).pdf
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
endif
|
||||
|
||||
ifeq ($(DOC),kernel-manual)
|
||||
XSLTOPTS = --stringparam html.stylesheet kernel-style.css \
|
||||
XSLTOPTS = --stringparam html.stylesheet style.css \
|
||||
--stringparam chapter.autolabel 1 \
|
||||
--stringparam appendix.autolabel A \
|
||||
--stringparam section.autolabel 1 \
|
||||
--stringparam section.label.includes.component.label 1 \
|
||||
--xinclude
|
||||
ALLPREQ = html pdf tarball
|
||||
TARFILES = kernel-manual.html kernel-manual.pdf kernel-style.css figures/kernel-title.png figures/kernel-architecture-overview.png
|
||||
TARFILES = kernel-manual.html kernel-manual.pdf style.css figures/kernel-title.png figures/kernel-architecture-overview.png
|
||||
MANUALS = $(DOC)/$(DOC).html $(DOC)/$(DOC).pdf
|
||||
FIGURES = figures
|
||||
STYLESHEET = $(DOC)/*.css
|
||||
@@ -246,47 +186,17 @@ all: $(ALLPREQ)
|
||||
pdf:
|
||||
ifeq ($(DOC),yocto-project-qs)
|
||||
@echo " "
|
||||
@echo "ERROR: You cannot generate a yocto-project-qs PDF file."
|
||||
@echo "ERROR: You cannot generate a PDF file for the Yocto Project Quick Start"
|
||||
@echo " "
|
||||
|
||||
else ifeq ($(DOC),mega-manual)
|
||||
@echo " "
|
||||
@echo "ERROR: You cannot generate a mega-manual PDF file."
|
||||
@echo " "
|
||||
|
||||
else
|
||||
|
||||
cd $(DOC); ../tools/poky-docbook-to-pdf $(DOC).xml ../template; cd ..
|
||||
endif
|
||||
|
||||
html:
|
||||
ifeq ($(DOC),mega-manual)
|
||||
# See http://www.sagehill.net/docbookxsl/HtmlOutput.html
|
||||
@echo " "
|
||||
@echo "******** Building "$(DOC)
|
||||
@echo " "
|
||||
cd $(DOC); xsltproc $(XSLTOPTS) -o $(DOC).html $(DOC)-customization.xsl $(DOC).xml; cd ..
|
||||
@echo " "
|
||||
@echo "******** Using mega-manual.sed to process external links"
|
||||
@echo " "
|
||||
cd $(DOC); sed -f ../tools/mega-manual.sed < mega-manual.html > mega-output.html; cd ..
|
||||
@echo " "
|
||||
@echo "******** Cleaning up transient file mega-output.html"
|
||||
@echo " "
|
||||
cd $(DOC); rm mega-manual.html; mv mega-output.html mega-manual.html; cd ..
|
||||
else
|
||||
# See http://www.sagehill.net/docbookxsl/HtmlOutput.html
|
||||
@echo " "
|
||||
@echo "******** Building "$(DOC)
|
||||
@echo " "
|
||||
cd $(DOC); xsltproc $(XSLTOPTS) -o $(DOC).html $(DOC)-customization.xsl $(DOC).xml; cd ..
|
||||
endif
|
||||
|
||||
|
||||
tarball: html
|
||||
@echo " "
|
||||
@echo "******** Creating Tarball of document files"
|
||||
@echo " "
|
||||
cd $(DOC); tar -cvzf $(DOC).tgz $(TARFILES); cd ..
|
||||
|
||||
validate:
|
||||
@@ -294,18 +204,8 @@ validate:
|
||||
|
||||
|
||||
publish:
|
||||
@if test -f $(DOC)/$(DOC).html; \
|
||||
then \
|
||||
echo " "; \
|
||||
echo "******** Publishing "$(DOC)".html"; \
|
||||
echo " "; \
|
||||
scp -r $(MANUALS) $(STYLESHEET) www.yoctoproject.org:/srv/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
|
||||
cd $(DOC); scp -r $(FIGURES) www.yoctoproject.org:/srv/www/www.yoctoproject.org-docs/$(VER)/$(DOC); \
|
||||
else \
|
||||
echo " "; \
|
||||
echo $(DOC)".html missing. Generate the file first then try again."; \
|
||||
echo " "; \
|
||||
fi
|
||||
scp -r $(MANUALS) $(STYLESHEET) www.yoctoproject.org:/srv/www/www.yoctoproject.org-docs/$(VER)/$(DOC)
|
||||
cd $(DOC); scp -r $(FIGURES) www.yoctoproject.org:/srv/www/www.yoctoproject.org-docs/$(VER)/$(DOC)
|
||||
|
||||
clean:
|
||||
rm -f $(MANUALS); rm $(DOC)/$(DOC).*tgz;
|
||||
rm -f $(MANUALS)
|
||||
|
||||
@@ -41,22 +41,8 @@ Folders exist for individual manuals as follows:
|
||||
* kernel-manual - The Yocto Project Kernel Architecture and Use Manual
|
||||
* poky-ref-manual - The Yocto Project Reference Manual
|
||||
* yocto-project-qs - The Yocto Project Quick Start
|
||||
* mega-manual - The aggregated manual comprised of all YP manuals and guides
|
||||
|
||||
Each folder is self-contained regarding content and figures. Note that there
|
||||
is a sed file needed to process the links of the mega-manual. The sed file
|
||||
is located in the tools directory. Also note that the figures folder in the
|
||||
mega-manual directory contains duplicates of all the figures in the YP folders
|
||||
directories for all YP manuals and guides.
|
||||
|
||||
If you want to find HTML versions of the Yocto Project manuals on the web,
|
||||
go to http://www.yoctoproject.org and click on the "Documentation" tab. From
|
||||
there you have access to archived documentation from previous releases, current
|
||||
documentation for the latest release, and "Docs in Progress" for the release
|
||||
currently being developed.
|
||||
|
||||
In general, the Yocto Project site (http://www.yoctoproject.org) is a great
|
||||
reference for both information and downloads.
|
||||
Each folder is self-contained regarding content and figures.
|
||||
|
||||
Makefile
|
||||
========
|
||||
@@ -85,10 +71,7 @@ Contains various templates, fonts, and some old PNG files.
|
||||
|
||||
tools
|
||||
=====
|
||||
Contains a tool to convert the DocBook files to PDF format. This folder also
|
||||
contains the mega-manual.sed file, which is used by Makefile to process
|
||||
cross-references from within the manual that normally go to an external
|
||||
manual.
|
||||
Contains a tool to convert the DocBook files to PDF format.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
<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
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>Build Directory</ulink>
|
||||
(see the section "<link linkend='using-an-existing-toolchain-tarball'>Using a Cross-Toolchain Tarball)</link>".
|
||||
which is outside of the build directory
|
||||
(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
|
||||
initializes a suitable cross-toolchain development environment.
|
||||
During the setup, locations for the compiler, QEMU scripts, QEMU binary,
|
||||
@@ -32,7 +32,7 @@
|
||||
For an Autotools-based project, you can use the cross-toolchain by just
|
||||
passing the appropriate host option to <filename>configure.sh</filename>.
|
||||
The host option you use is derived from the name of the environment setup
|
||||
script in <filename>/opt/poky</filename> resulting from installation of the
|
||||
script in <filename>/opt/poky</filename> resulting from unpacking the
|
||||
cross-toolchain tarball.
|
||||
For example, the host option for an ARM-based target that uses the GNU EABI
|
||||
is <filename>armv5te-poky-linux-gnueabi</filename>.
|
||||
|
||||
740
documentation/adt-manual/adt-eclipse.xml
Normal file
@@ -0,0 +1,740 @@
|
||||
<!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 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>
|
||||
This section describes how to install and configure the Eclipse IDE
|
||||
Yocto Plug-in and how to use it to develop your application.
|
||||
</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>
|
||||
<note>
|
||||
Do not install Eclipse from your distribution's package repository.
|
||||
Be sure to install Eclipse from the official Eclipse download site as directed
|
||||
in the next section.
|
||||
</note>
|
||||
</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.2-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's Eclipse 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 Project 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 build directory.
|
||||
When you select <filename>Build system derived toolchain</filename>,
|
||||
you are using the toolchain bundled
|
||||
inside the build directory.
|
||||
</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 build directory.
|
||||
See section "<link linkend='using-the-toolchain-from-within-the-build-tree'>Using
|
||||
BitBake and the build directory</link>" for
|
||||
information on how to install the toolchain into the build directory.</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
|
||||
build directory 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 Project 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 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>Yocot Project 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>Yocto Project 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 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 to your
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#yocto-project-source-files'>source directory structure</ulink>
|
||||
by defining "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,61 +3,54 @@
|
||||
[<!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.
|
||||
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>
|
||||
|
||||
<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.
|
||||
</para>
|
||||
|
||||
<section id='adt-intro-section'>
|
||||
<title>The Application Development Toolkit (ADT)</title>
|
||||
<section id='book-intro'>
|
||||
<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 OpenEmbedded 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>
|
||||
|
||||
<para>
|
||||
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, a toolchain installer
|
||||
script, or through a
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>Build Directory</ulink> that
|
||||
is based on your metadata
|
||||
This toolchain is created either by running the ADT Installer script or
|
||||
through a build directory that is based on your metadata
|
||||
configuration or extension for your targeted device.
|
||||
The cross-toolchain works with a matching target sysroot.
|
||||
</para>
|
||||
@@ -75,33 +68,6 @@
|
||||
</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>
|
||||
|
||||
@@ -113,9 +79,7 @@
|
||||
<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
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>Source Directory</ulink> and
|
||||
you have sourced
|
||||
it to create a source directory and you have sourced
|
||||
the environment setup script, QEMU is installed and automatically
|
||||
available.</para></listitem>
|
||||
<listitem><para>If you have installed the cross-toolchain
|
||||
@@ -143,7 +107,7 @@
|
||||
<listitem><para><emphasis>PowerTOP:</emphasis> Helps you determine what
|
||||
software is using the most power.
|
||||
You can find out more about PowerTOP at
|
||||
<ulink url='https://01.org/powertop/'></ulink>.</para></listitem>
|
||||
<ulink url='http://www.linuxpowertop.org/'></ulink>.</para></listitem>
|
||||
<listitem><para><emphasis>OProfile:</emphasis> A system-wide profiler for Linux
|
||||
systems that is capable of profiling all running code at low overhead.
|
||||
You can find out more about OProfile at
|
||||
|
||||
@@ -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>
|
||||
@@ -51,19 +51,9 @@
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>October 2012</date>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.1</revnumber>
|
||||
<date>April 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.2</revnumber>
|
||||
<date>May 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
<copyright>
|
||||
@@ -73,13 +63,14 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
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
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>Yocto Project Application Developer's Guide</ulink> on
|
||||
documentation bundled in the release tarball and the
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>
|
||||
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>
|
||||
@@ -94,6 +85,8 @@
|
||||
|
||||
<xi:include href="adt-package.xml"/>
|
||||
|
||||
<xi:include href="adt-eclipse.xml"/>
|
||||
|
||||
<xi:include href="adt-command.xml"/>
|
||||
|
||||
<!-- <index id='index'>
|
||||
@@ -102,6 +95,6 @@
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -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 source directory.
|
||||
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,32 +4,32 @@
|
||||
|
||||
<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.
|
||||
Cross-Development Environment</link>"
|
||||
section for more information.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>Avoid mixing installation methods when installing toolchains for different architectures.
|
||||
<para>Avoid mixing installation methods when installing the ADT for different architectures.
|
||||
For example, avoid using the ADT Installer to install some toolchains and then hand-installing
|
||||
cross-development toolchains by running the toolchain installer for different architectures.
|
||||
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
|
||||
@@ -45,15 +45,14 @@
|
||||
For example, you can configure the installation to install the QEMU emulator
|
||||
and the user-space NFS, specify which root filesystem profiles to download,
|
||||
and define the target sysroot location.</para></listitem>
|
||||
<listitem><para><emphasis>Use an Existing Toolchain:</emphasis>
|
||||
<listitem><para><emphasis>Use an Existing Toolchain Tarball:</emphasis>
|
||||
Using this method, you select and download an architecture-specific
|
||||
toolchain installer and then run the script to hand-install the toolchain.
|
||||
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 build directory, you can build the cross-toolchain
|
||||
within that structure.
|
||||
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>
|
||||
@@ -63,16 +62,8 @@
|
||||
<title>Using the ADT Installer</title>
|
||||
|
||||
<para>
|
||||
To run the ADT Installer, you need to get the ADT Installer tarball, be sure
|
||||
you have the necessary host development packages that support the ADT Installer,
|
||||
and then run the ADT Installer Script.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For a list of the host packages needed to support ADT installation and use, see the
|
||||
"ADT Installer Extras" lists in the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#required-packages-for-the-host-development-system'>Required Packages for the Host Development System</ulink>" section
|
||||
of the Yocto Project Reference Manual.
|
||||
To run the ADT Installer, you need to first get the ADT Installer tarball and then run the ADT
|
||||
Installer Script.
|
||||
</para>
|
||||
|
||||
<section id='getting-the-adt-installer-tarball'>
|
||||
@@ -84,22 +75,21 @@
|
||||
<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 build directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you use BitBake to generate the ADT Installer tarball, you must
|
||||
<filename>source</filename> the environment setup script
|
||||
(<filename>&OE_INIT_FILE;</filename>) located
|
||||
in the Source Directory before running the <filename>bitbake</filename>
|
||||
(<filename>oe-init-build-env</filename>) located
|
||||
in the source directory 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
|
||||
source directory, set up the environment while also creating the
|
||||
default build directory,
|
||||
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'>
|
||||
@@ -128,16 +118,13 @@
|
||||
$ cp ~/poky/build/tmp/deploy/sdk/adt_installer.tar.bz2 $HOME
|
||||
$ tar -xjf adt_installer.tar.bz2
|
||||
</literallayout>
|
||||
Unpacking the tarball creates the directory <filename>adt-installer</filename>,
|
||||
which contains the ADT Installer script (<filename>adt_installer</filename>),
|
||||
its configuration file (<filename>adt_installer.conf</filename>), a
|
||||
<filename>scripts</filename> directory, and an <filename>opkg</filename>
|
||||
directory.
|
||||
Unpacking it creates the directory <filename>adt-installer</filename>,
|
||||
which contains the ADT Installer script (<filename>adt_installer</filename>)
|
||||
and its configuration file (<filename>adt_installer.conf</filename>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Before you run the ADT Installer script, however, you should examine
|
||||
the ADT Installer configuration
|
||||
Before you run the script, however, you should examine the ADT Installer configuration
|
||||
file and be sure you are going to get what you want.
|
||||
Your configurations determine which kernel and filesystem image are downloaded.
|
||||
</para>
|
||||
@@ -155,22 +142,7 @@
|
||||
<filename>YOCTOADT_REPO</filename>, you need to be sure that the
|
||||
directory structure follows the same layout as the reference directory
|
||||
set up at <ulink url='http://adtrepo.yoctoproject.org'></ulink>.
|
||||
Also, your repository needs to be accessible through HTTP.</para>
|
||||
<para>Additionally, you will need to edit a second configuration file
|
||||
located in the <filename>adt-installer/opkg</filename> directory.
|
||||
The configuration file you edit depends on your host development
|
||||
system.
|
||||
For 64-bit systems, edit the <filename>opkg-sdk-x86_64.conf</filename>
|
||||
file.
|
||||
If your host development system is 32-bit, edit the
|
||||
<filename>opkg-sdk-i686.conf</filename> file.
|
||||
For both cases, you need to make sure you are pointing to
|
||||
the IPKG-based packages specified by the
|
||||
<filename>YOCTOADT_REPO</filename>.
|
||||
Here is an example for a 64-bit development system:
|
||||
<literallayout class='monospaced'>
|
||||
src yp-x86_64-nativesdk http://my_repo/yp-1.3.1/adt-ipk/x86_64-nativesdk
|
||||
</literallayout></para></listitem>
|
||||
Also, your repository needs to be accessible through HTTP.</para></listitem>
|
||||
<listitem><para><filename>YOCTOADT_TARGETS</filename>: The machine
|
||||
target architectures for which you want to set up cross-development
|
||||
environments.</para></listitem>
|
||||
@@ -213,13 +185,19 @@
|
||||
When you run the installer, the environment must use a
|
||||
host <filename>gcc</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/adt-installer
|
||||
$ ./adt_installer
|
||||
</literallayout>
|
||||
Once the installer begins to run, you are asked to enter the location for
|
||||
cross-toolchain installation.
|
||||
The default location is <filename>/opt/poky/<release></filename>.
|
||||
After selecting the location, you are prompted to run in
|
||||
</para>
|
||||
|
||||
<note>
|
||||
The ADT Installer requires the <filename>libtool</filename> package to complete.
|
||||
If you install the recommended packages as described in
|
||||
"<ulink url='&YOCTO_DOCS_QS_URL;#packages'>The Packages</ulink>"
|
||||
section of The Yocto Project Quick Start, then you will have libtool installed.
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Once the installer begins to run, you are asked whether you want to run in
|
||||
interactive or silent mode.
|
||||
If you want to closely monitor the installation, choose “I” for interactive
|
||||
mode rather than “S” for silent mode.
|
||||
@@ -242,12 +220,10 @@
|
||||
<title>Using a Cross-Toolchain Tarball</title>
|
||||
|
||||
<para>
|
||||
If you want to simply install the cross-toolchain by hand, you can do so by running the
|
||||
toolchain installer.
|
||||
If you want to simply install the cross-toolchain by hand, you can do so by using an existing
|
||||
cross-toolchain tarball.
|
||||
If you use this method to install the cross-toolchain and you still need to install the target
|
||||
sysroot, you will have to extract and install sysroot separately.
|
||||
For information on how to do this, see the
|
||||
"<link linkend='extracting-the-root-filesystem'>Extracting the Root Filesystem</link>" section.
|
||||
sysroot, you will have to install sysroot separately.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -258,43 +234,30 @@
|
||||
and find the folder that matches your host development system
|
||||
(i.e. <filename>i686</filename> for 32-bit machines or
|
||||
<filename>x86-64</filename> for 64-bit machines).</para></listitem>
|
||||
<listitem><para>Go into that folder and download the toolchain installer whose name
|
||||
<listitem><para>Go into that folder and download the toolchain tarball whose name
|
||||
includes the appropriate target architecture.
|
||||
For example, if your host development system is an Intel-based 64-bit system and
|
||||
you are going to use your cross-toolchain for an Intel-based 32-bit target, go into the
|
||||
<filename>x86_64</filename> folder and download the following installer:
|
||||
<filename>x86_64</filename> folder and download the following tarball:
|
||||
<literallayout class='monospaced'>
|
||||
poky-eglibc-x86_64-i586-toolchain-gmae-&DISTRO;.sh
|
||||
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 installer
|
||||
if you have a <ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>Build Directory</ulink>.
|
||||
<note><para>As an alternative to steps one and two, you can build the toolchain tarball
|
||||
if you have a build directory.
|
||||
If you need GMAE, you should use the <filename>bitbake meta-toolchain-gmae</filename>
|
||||
command.
|
||||
The resulting installation script when run will support such development.
|
||||
The resulting tarball will support such development.
|
||||
However, if you are not concerned with GMAE,
|
||||
you can generate the toolchain installer using
|
||||
<filename>bitbake meta-toolchain</filename>.</para>
|
||||
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_INIT_PATH;</filename> script located in the Source
|
||||
Directory.
|
||||
When the <filename>bitbake</filename> command completes, the toolchain installer will
|
||||
be in <filename>tmp/deploy/sdk</filename> in the Build Directory.
|
||||
</para></note>
|
||||
</para></listitem>
|
||||
<listitem><para>Once you have the installer, run it to install the toolchain.
|
||||
You must change the permissions on the toolchain installer
|
||||
script so that it is executable.</para>
|
||||
<para>The following command shows how to run the installer given a toolchain tarball
|
||||
for a 64-bit development host system and a 32-bit target architecture.
|
||||
The example assumes the toolchain installer is located in <filename>~/Downloads/</filename>.
|
||||
<literallayout class='monospaced'>
|
||||
$ ~/Downloads/poky-eglibc-x86_64-i586-toolchain-gmae-&DISTRO;.sh
|
||||
</literallayout>
|
||||
<note>
|
||||
If you do not have write permissions for the directory into which you are installing
|
||||
the toolchain, the toolchain installer notifies you and exits.
|
||||
Be sure you have write permissions in the directory and run the installer again.
|
||||
</note>
|
||||
sourced the <filename>oe-build-init-env</filename> script located in the source
|
||||
directory.
|
||||
When the <filename>bitbake</filename> command completes, the tarball will
|
||||
be in <filename>tmp/deploy/sdk</filename> in the build directory.
|
||||
</para></note></para></listitem>
|
||||
<listitem><para>Make sure you are in the root directory with root privileges and then expand
|
||||
the tarball.
|
||||
The tarball expands into <filename>&YOCTO_ADTPATH_DIR;</filename>.
|
||||
Once the tarball is expanded, the cross-toolchain is installed.
|
||||
You will notice environment setup files for the cross-toolchain in the directory.
|
||||
</para></listitem>
|
||||
@@ -307,29 +270,27 @@
|
||||
|
||||
<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>.
|
||||
to generate the toolchain within an existing build directory.
|
||||
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 generate the toolchain into the build tree:
|
||||
<orderedlist>
|
||||
<listitem><para>Source the environment setup script
|
||||
<filename>&OE_INIT_FILE;</filename> located in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>Source Directory</ulink>.
|
||||
<filename>oe-init-build-env</filename> located in the source directory.
|
||||
</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 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
|
||||
@@ -343,14 +304,10 @@
|
||||
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 cross-toolchain is generated and populated within the build directory.
|
||||
You will notice environment setup files for the cross-toolchain in the
|
||||
Build Directory in the <filename>tmp</filename> directory.
|
||||
Setup script filenames contain the strings <filename>environment-setup</filename>.</para>
|
||||
<para>Be aware that when you use this method to install the toolchain you still need
|
||||
to separately extract and install the sysroot filesystem.
|
||||
For information on how to do this, see the
|
||||
"<link linkend='extracting-the-root-filesystem'>Extracting the Root Filesystem</link>" section.
|
||||
build directory in the <filename>tmp</filename> directory.
|
||||
Setup script filenames contain the strings <filename>environment-setup</filename>.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
@@ -363,13 +320,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 build directory's <filename>tmp</filename> directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -403,7 +358,7 @@
|
||||
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>
|
||||
@@ -416,20 +371,12 @@
|
||||
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.
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Reference: Images</ulink>" appendix in
|
||||
The Yocto Project Reference Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you are planning on developing against your image and you are not
|
||||
building or using one of the Yocto Project development images
|
||||
(e.g. core-image-*-dev), you must be sure to include the development
|
||||
packages as part of your image recipe.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Furthermore, if you plan on remotely deploying and debugging your
|
||||
application from within the
|
||||
If you plan on remotely deploying and debugging your application from within the
|
||||
Eclipse IDE, you must have an image that contains the Yocto Target Communication
|
||||
Framework (TCF) agent (<filename>tcf-agent</filename>).
|
||||
By default, the Yocto Project provides only one type pre-built image that contains the
|
||||
@@ -442,10 +389,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 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>
|
||||
@@ -453,7 +398,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
|
||||
@@ -466,8 +411,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>.
|
||||
|
||||
|
Before Width: | Height: | Size: 13 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>
|
||||
@@ -63,19 +63,9 @@
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>October 2012</date>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.1</revnumber>
|
||||
<date>April 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.2</revnumber>
|
||||
<date>May 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
<copyright>
|
||||
@@ -85,13 +75,14 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
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
|
||||
<ulink url='&YOCTO_DOCS_BSP_URL;'>Yocto Project Board Support Package (BSP) Developer's Guide</ulink> on
|
||||
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.
|
||||
For the latest version of this manual, see the manual on the website.
|
||||
</note>
|
||||
@@ -107,6 +98,6 @@
|
||||
-->
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This guide presents information about BSP Layers, defines a structure for components
|
||||
This chapter (or document if you are reading the BSP Developer's Guide)
|
||||
talks about BSP Layers, defines a structure for components
|
||||
so that BSPs follow a commonly understood layout, discusses how to customize
|
||||
a recipe for a BSP, addresses BSP licensing, and provides information that
|
||||
shows you how to create and manage a
|
||||
@@ -47,7 +48,7 @@
|
||||
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>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
Adding the root allows the OpenEmbedded build system to recognize the BSP
|
||||
definition and from it build an image.
|
||||
Here is an example:
|
||||
@@ -55,7 +56,6 @@
|
||||
BBLAYERS = " \
|
||||
/usr/local/src/yocto/meta \
|
||||
/usr/local/src/yocto/meta-yocto \
|
||||
/usr/local/src/yocto/meta-yocto-bsp \
|
||||
/usr/local/src/yocto/meta-<bsp_name> \
|
||||
"
|
||||
</literallayout>
|
||||
@@ -83,6 +83,8 @@
|
||||
For more detailed information on layers, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#understanding-and-creating-layers'>Understanding and Creating Layers</ulink>"
|
||||
section of the Yocto Project Development Manual.
|
||||
You can also see the detailed examples in the appendices of
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;'>The Yocto Project Development Manual</ulink>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -170,6 +172,9 @@
|
||||
meta-crownbay/recipes-bsp/formfactor/formfactor/crownbay/machconfig
|
||||
meta-crownbay/recipes-bsp/formfactor/formfactor/crownbay-noemgd/
|
||||
meta-crownbay/recipes-bsp/formfactor/formfactor/crownbay-noemgd/machconfig
|
||||
meta-crownbay/recipes-core/
|
||||
meta-crownbay/recipes-core/tasks/
|
||||
meta-crownbay/recipes-core/tasks/task-core-tools-profile.bbappend
|
||||
meta-crownbay/recipes-graphics/
|
||||
meta-crownbay/recipes-graphics/xorg-xserver/
|
||||
meta-crownbay/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend
|
||||
@@ -180,10 +185,9 @@
|
||||
meta-crownbay/recipes-graphics/xorg-xserver/xserver-xf86-config/crownbay-noemgd/xorg.conf
|
||||
meta-crownbay/recipes-kernel/
|
||||
meta-crownbay/recipes-kernel/linux/
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto-rt_3.2.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto-rt_3.4.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_3.2.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_3.4.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto-rt_3.0.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_2.6.37.bbappend
|
||||
meta-crownbay/recipes-kernel/linux/linux-yocto_3.0.bbappend
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -310,8 +314,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}/"
|
||||
@@ -387,7 +391,7 @@
|
||||
<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>.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</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>.
|
||||
@@ -398,8 +402,8 @@
|
||||
For example, the Crown Bay BSP <filename>crownbay.conf</filename> has the
|
||||
following statements:
|
||||
<literallayout class='monospaced'>
|
||||
require conf/machine/include/tune-atom.inc
|
||||
require conf/machine/include/ia32-base.inc
|
||||
include conf/machine/include/tune-atom.inc
|
||||
include conf/machine/include/ia32-base.inc
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
@@ -439,10 +443,31 @@
|
||||
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;#source-directory'>source directory</ulink>.
|
||||
</para></note>
|
||||
</section>
|
||||
|
||||
<section id='bsp-filelayout-core-recipes'>
|
||||
<title>Core Recipe Files</title>
|
||||
<para>
|
||||
You can find these files in the BSP Layer at:
|
||||
<literallayout class='monospaced'>
|
||||
meta-<bsp_name>/recipes-core/*
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This directory contains recipe files that are almost always necessary to build a
|
||||
useful, working Linux image.
|
||||
Thus, the term "core" is used to group these recipes.
|
||||
For example, in the Crown Bay BSP there is the
|
||||
<filename>task-core-tools-profile.bbappend</filename> file, which is an append file used
|
||||
to recommend that the
|
||||
<ulink url='http://sourceware.org/systemtap/wiki'>SystemTap</ulink>
|
||||
package be included as a package when the image is built.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='bsp-filelayout-recipes-graphics'>
|
||||
<title>Display Support Files</title>
|
||||
<para>
|
||||
@@ -480,39 +505,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>
|
||||
For your BSP, you typically want to use an existing Yocto Project kernel found in the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</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 these types
|
||||
of statements:
|
||||
<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>
|
||||
<note>
|
||||
When the preferred provider is assumed by default, the
|
||||
<filename>PREFERRED_PROVIDER</filename> statement does not appear in the
|
||||
<filename><bsp_name>.conf</filename> file.
|
||||
</note>
|
||||
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
|
||||
@@ -522,99 +541,82 @@
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
COMPATIBLE_MACHINE_crownbay = "crownbay"
|
||||
KMACHINE_crownbay = "crownbay"
|
||||
KBRANCH_crownbay = "standard/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/crownbay"
|
||||
KMACHINE_crownbay-noemgd = "yocto/standard/crownbay"
|
||||
KERNEL_FEATURES_append_crownbay-noemgd += " cfg/smp.scc"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "449f7f520350700858f21a5554b81cc8ad23267d"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "9e3bdb7344054264b750e53fbbb6394cc1c942ac"
|
||||
SRCREV_emgd_pn-linux-yocto_crownbay ?= "86643bdd8cbad616a161ab91f51108cf0da827bc"
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "63c65842a3a74e4bd3128004ac29b5639f16433f"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "59314a3523e360796419d76d78c6f7d8c5ef2593"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay-noemgd ?= "449f7f520350700858f21a5554b81cc8ad23267d"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay-noemgd ?= "9e3bdb7344054264b750e53fbbb6394cc1c942ac"
|
||||
|
||||
KSRC_linux_yocto_3_4 ?= "git.yoctoproject.org/linux-yocto-3.4.git"
|
||||
SRC_URI_crownbay = "git://git.yoctoproject.org/linux-yocto-3.4.git;protocol=git;nocheckout=1;branch=${KBRANCH},meta,emgd-1.14;name=machine,meta,emgd"
|
||||
SRC_URI_crownbay-noemgd = "git://git.yoctoproject.org/linux-yocto-3.4.git;protocol=git;nocheckout=1;branch=${KBRANCH},meta;name=machine,meta"
|
||||
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/crownbay"
|
||||
KMACHINE_crownbay = "yocto/standard/crownbay"
|
||||
KERNEL_FEATURES_append_crownbay += " cfg/smp.scc"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= "449f7f520350700858f21a5554b81cc8ad23267d"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= "9e3bdb7344054264b750e53fbbb6394cc1c942ac"
|
||||
SRCREV_emgd_pn-linux-yocto_crownbay ?= "86643bdd8cbad616a161ab91f51108cf0da827bc"
|
||||
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 specific 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;#build-directory'>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;#source-directory'>source directory</ulink> Git
|
||||
repository and the <filename>meta</filename> Git repository branches to identify the
|
||||
exact kernel needed to build the Crown Bay BSP.
|
||||
<note>
|
||||
For <filename>crownbay</filename>, a specific commit is also needed to point
|
||||
to the branch that supports EMGD graphics.
|
||||
At a minimum, every BSP points to the
|
||||
<filename>machine</filename> and <filename>meta</filename> commits.
|
||||
</note>
|
||||
</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.
|
||||
@@ -623,29 +625,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.
|
||||
</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>
|
||||
<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>
|
||||
@@ -716,7 +721,7 @@
|
||||
<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>,
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>source directory</ulink>,
|
||||
or in the OpenEmbedded Core Layer
|
||||
(<filename>openembedded-core</filename>) found at
|
||||
<ulink url='http://git.openembedded.org/openembedded-core/tree/meta'></ulink>.
|
||||
@@ -724,7 +729,7 @@
|
||||
<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 source directory (<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
|
||||
@@ -740,22 +745,22 @@
|
||||
You must specify which license to use since there is no
|
||||
default license if one is not specified.
|
||||
See the
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fri2/COPYING.MIT'><filename>COPYING.MIT</filename></ulink>
|
||||
file for the Fish River Island 2 BSP in the <filename>meta-fri2</filename> BSP layer
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fishriver/COPYING.MIT'><filename>COPYING.MIT</filename></ulink>
|
||||
file for the Fish River BSP in the <filename>meta-fishriver</filename> BSP layer
|
||||
as an example.</para></listitem>
|
||||
<listitem><para><emphasis>README File:</emphasis>
|
||||
You must include a <filename>README</filename> file in the
|
||||
<filename>meta-<bsp_name></filename> directory.
|
||||
See the
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fri2/README'><filename>README</filename></ulink>
|
||||
file for the Fish River Island 2 BSP in the <filename>meta-fri2</filename> BSP layer
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fishriver/README'><filename>README</filename></ulink>
|
||||
file for the Fish River BSP in the <filename>meta-fishriver</filename> BSP layer
|
||||
as an example.</para>
|
||||
<para>At a minimum, the <filename>README</filename> file should
|
||||
contain the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>A brief description about the hardware the BSP
|
||||
targets.</para></listitem>
|
||||
<listitem><para>A list of all the dependencies
|
||||
<listitem><para>A list of all the dependencies a
|
||||
on which a BSP layer depends.
|
||||
These dependencies are typically a list of required layers needed
|
||||
to build the BSP.
|
||||
@@ -788,8 +793,8 @@
|
||||
generate the binary images contained in the
|
||||
<filename>/binary</filename> directory, if present.
|
||||
See the
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fri2/README.sources'><filename>README.sources</filename></ulink>
|
||||
file for the Fish River Island 2 BSP in the <filename>meta-fri2</filename> BSP layer
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/meta-intel/tree/meta-fishriver/README.sources'><filename>README.sources</filename></ulink>
|
||||
file for the Fish River BSP in the <filename>meta-fishriver</filename> BSP layer
|
||||
as an example.</para></listitem>
|
||||
<listitem><para><emphasis>Layer Configuration File:</emphasis>
|
||||
You must include a <filename>conf/layer.conf</filename> in the
|
||||
@@ -803,13 +808,14 @@
|
||||
using the BSP layer.
|
||||
Multiple machine configuration files define variations of machine
|
||||
configurations that are supported by the BSP.
|
||||
If a BSP supports multiple machine variations, you need to
|
||||
If a BSP supports more multiple machine variations, you need to
|
||||
adequately describe each variation in the BSP
|
||||
<filename>README</filename> file.
|
||||
Do not use multiple machine configuration files to describe disparate
|
||||
hardware.
|
||||
If you do have very different targets, you should create separate
|
||||
BSP layers for each target.
|
||||
Multiple machine configuration files should describe very similar targets.
|
||||
If you do have very different targets, you should create a separate
|
||||
BSP.
|
||||
<note>It is completely possible for a developer to structure the
|
||||
working repository as a conglomeration of unrelated BSP
|
||||
files, and to possibly generate specifically targeted 'release' BSPs
|
||||
@@ -855,7 +861,7 @@
|
||||
Basing your recipes on these kernels reduces the costs for maintaining
|
||||
the BSP and increases its scalability.
|
||||
See the <filename>Yocto Linux Kernel</filename> category in the
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'>Source Repositories</ulink>
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'><filename>Yocto Source Repositories</filename></ulink>
|
||||
for these kernels.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
@@ -880,7 +886,7 @@
|
||||
<para>
|
||||
To better understand this, consider an example that customizes a recipe by adding
|
||||
a BSP-specific configuration file named <filename>interfaces</filename> to the
|
||||
<filename>netbase_5.0.bb</filename> recipe for machine "xyz".
|
||||
<filename>netbase_4.47.bb</filename> recipe for machine "xyz".
|
||||
Do the following:
|
||||
<orderedlist>
|
||||
<listitem><para>Edit the <filename>netbase_4.47.bbappend</filename> file so that it
|
||||
@@ -1026,8 +1032,8 @@
|
||||
|
||||
<para>
|
||||
The following sections describe the common location and help features as well
|
||||
as provide details for the
|
||||
<filename>yocto-bsp</filename> and <filename>yocto-kernel</filename> tools.
|
||||
as details for the <filename>yocto-bsp</filename> and <filename>yocto-kernel</filename>
|
||||
tools.
|
||||
</para>
|
||||
|
||||
<section id='common-features'>
|
||||
@@ -1046,7 +1052,7 @@
|
||||
|
||||
<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;#source-directory'>source directory</ulink>.
|
||||
Consequently, to use the scripts, you must <filename>source</filename> the
|
||||
environment just as you would when invoking a build:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -1058,27 +1064,30 @@
|
||||
The most immediately useful function is to get help on both tools.
|
||||
The built-in help system makes it easy to drill down at
|
||||
any time and view the syntax required for any specific command.
|
||||
Simply enter the name of the command with the <filename>help</filename>
|
||||
switch:
|
||||
Simply enter the name of the command, or the command along with
|
||||
<filename>help</filename> to display a list of the available sub-commands.
|
||||
Here is an example:
|
||||
<literallayout class='monospaced'>
|
||||
$ yocto-bsp
|
||||
$ yocto-bsp help
|
||||
Usage:
|
||||
|
||||
Create a customized Yocto BSP layer.
|
||||
Usage:
|
||||
|
||||
usage: yocto-bsp [--version] [--help] COMMAND [ARGS]
|
||||
Create a customized Yocto BSP layer.
|
||||
|
||||
Current 'yocto-bsp' commands are:
|
||||
create Create a new Yocto BSP
|
||||
list List available values for options and BSP properties
|
||||
usage: yocto-bsp [--version] [--help] COMMAND [ARGS]
|
||||
|
||||
See 'yocto-bsp help COMMAND' for more information on a specific command.
|
||||
The most commonly used 'yocto-bsp' commands are:
|
||||
create Create a new Yocto BSP
|
||||
list List available values for options and BSP properties
|
||||
|
||||
See 'yocto-bsp help COMMAND' for more information on a specific command.
|
||||
|
||||
|
||||
Options:
|
||||
--version show program's version number and exit
|
||||
-h, --help show this help message and exit
|
||||
-D, --debug output debug information
|
||||
--version show program's version number and exit
|
||||
-h, --help show this help message and exit
|
||||
-D, --debug output debug information
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -1088,20 +1097,19 @@
|
||||
<literallayout class='monospaced'>
|
||||
$ yocto-bsp create
|
||||
|
||||
Usage:
|
||||
Usage:
|
||||
|
||||
Create a new Yocto BSP
|
||||
|
||||
usage: yocto-bsp create <bsp-name> <karch> [-o <DIRNAME> | --outdir <DIRNAME>]
|
||||
Create a new Yocto BSP
|
||||
usage: yocto-bsp create <bsp-name> <karch> [-o <DIRNAME> | --outdir <DIRNAME>]
|
||||
[-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 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.
|
||||
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 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.
|
||||
|
||||
...
|
||||
...
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -1112,26 +1120,33 @@
|
||||
$ yocto-bsp help create
|
||||
|
||||
NAME
|
||||
yocto-bsp create - Create a new Yocto BSP
|
||||
yocto-bsp create - Create a new Yocto BSP
|
||||
|
||||
SYNOPSIS
|
||||
yocto-bsp create <bsp-name> <karch> [-o <DIRNAME> | --outdir <DIRNAME>]
|
||||
yocto-bsp create <bsp-name> <karch> [-o <DIRNAME> | --outdir <DIRNAME>]
|
||||
[-i <JSON PROPERTY FILE> | --infile <JSON PROPERTY_FILE>]
|
||||
|
||||
DESCRIPTION
|
||||
This command creates a Yocto BSP based on the specified
|
||||
parameters. 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.
|
||||
|
||||
The value of the 'karch' parameter determines the set of files
|
||||
that will be generated for the BSP, along with the specific set of
|
||||
'properties' that will be used to fill out the BSP-specific
|
||||
portions of the BSP. The possible values for the 'karch' paramter
|
||||
can be listed via 'yocto-bsp list karch'.
|
||||
|
||||
...
|
||||
This command creates a Yocto BSP based on the specified
|
||||
parameters. 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.
|
||||
|
||||
The value of the 'karch' parameter determines the set of files
|
||||
that will be generated for the BSP, along with the specific set of
|
||||
'properties' that will be used to fill out the BSP-specific
|
||||
portions of the BSP.
|
||||
|
||||
...
|
||||
|
||||
NOTE: Once created, you should add your new layer to your
|
||||
bblayers.conf file in order for it to be subsequently seen and
|
||||
modified by the yocto-kernel tool.
|
||||
|
||||
NOTE for x86- and x86_64-based BSPs: The generated BSP assumes the
|
||||
presence of the of the meta-intel layer, so you should also have a
|
||||
meta-intel layer present and added to your bblayers.conf as well.
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -1158,33 +1173,33 @@
|
||||
For the current set of BSPs, the script prompts you for various important
|
||||
parameters such as:
|
||||
<itemizedlist>
|
||||
<listitem><para>The kernel to use</para></listitem>
|
||||
<listitem><para>The branch of that kernel to use (or re-use)</para></listitem>
|
||||
<listitem><para>Whether or not to use X, and if so, which drivers to use</para></listitem>
|
||||
<listitem><para>Whether to turn on SMP</para></listitem>
|
||||
<listitem><para>Whether the BSP has a keyboard</para></listitem>
|
||||
<listitem><para>Whether the BSP has a touchscreen</para></listitem>
|
||||
<listitem><para>Remaining configurable items associated with the BSP</para></listitem>
|
||||
<listitem><para>which kernel to use</para></listitem>
|
||||
<listitem><para>which branch of that kernel to use (or re-use)</para></listitem>
|
||||
<listitem><para>whether or not to use X, and if so, which drivers to use</para></listitem>
|
||||
<listitem><para>whether to turn on SMP</para></listitem>
|
||||
<listitem><para>whether the BSP has a keyboard</para></listitem>
|
||||
<listitem><para>whether the BSP has a touchscreen</para></listitem>
|
||||
<listitem><para>any remaining configurable items associated with the BSP</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You use the <filename>yocto-bsp create</filename> sub-command to create
|
||||
a new BSP layer.
|
||||
This command requires you to specify a particular kernel architecture
|
||||
(<filename>karch</filename>) on which to base the BSP.
|
||||
This command requires you to specify a particular architecture on which to
|
||||
base the BSP.
|
||||
Assuming you have sourced the environment, you can use the
|
||||
<filename>yocto-bsp list karch</filename> sub-command to list the
|
||||
architectures available for BSP creation as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ yocto-bsp list karch
|
||||
Architectures available:
|
||||
qemu
|
||||
x86_64
|
||||
i386
|
||||
powerpc
|
||||
arm
|
||||
powerpc
|
||||
i386
|
||||
mips
|
||||
x86_64
|
||||
qemu
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -1205,46 +1220,53 @@
|
||||
the prompts appear in brackets.
|
||||
Pressing enter without supplying anything on the command line or pressing enter
|
||||
and providing an invalid response causes the script to accept the default value.
|
||||
Once the script completes, the new <filename>meta-myarm</filename> BSP layer
|
||||
is created in the current working directory.
|
||||
This example assumes you have source the &OE_INIT_FILE; and are currently
|
||||
in the top-level folder of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>Source Directory</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Following is the complete example:
|
||||
<literallayout class='monospaced'>
|
||||
$ yocto-bsp create myarm qemu
|
||||
Which qemu architecture would you like to use? [default: i386]
|
||||
1) i386 (32-bit)
|
||||
2) x86_64 (64-bit)
|
||||
3) ARM (32-bit)
|
||||
4) PowerPC (32-bit)
|
||||
5) MIPS (32-bit)
|
||||
Which qemu architecture would you like to use? [default: x86]
|
||||
1) common 32-bit x86
|
||||
2) common 64-bit x86
|
||||
3) common 32-bit ARM
|
||||
4) common 32-bit PowerPC
|
||||
5) common 32-bit MIPS
|
||||
3
|
||||
Would you like to use the default (3.4) kernel? (y/n) [default: y]
|
||||
Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [y/n] [default: y]
|
||||
Getting branches from remote repo git://git.yoctoproject.org/linux-yocto-3.4.git...
|
||||
Please choose a machine branch to base your new BSP branch on: [default: standard/base]
|
||||
1) standard/arm-versatile-926ejs
|
||||
Would you like to use the default (3.2) kernel? (Y/n)
|
||||
Do you need a new machine branch for this BSP (the alternative is to re-use an existing branch)? [Y/n]
|
||||
Getting branches from remote repo git://git.yoctoproject.org/linux-yocto-3.2...
|
||||
Please choose a machine branch to base this BSP on => [default: standard/default/common-pc]
|
||||
1) base
|
||||
2) standard/base
|
||||
3) standard/beagleboard
|
||||
4) standard/cedartrail
|
||||
5) standard/crownbay
|
||||
6) standard/emenlow
|
||||
7) standard/fishriver
|
||||
8) standard/fri2
|
||||
9) standard/fsl-mpc8315e-rdb
|
||||
10) standard/mti-malta32
|
||||
11) standard/mti-malta64
|
||||
12) standard/qemuppc
|
||||
13) standard/routerstationpro
|
||||
14) standard/sys940x
|
||||
1
|
||||
Would you like SMP support? (y/n) [default: y]
|
||||
Does your BSP have a touchscreen? (y/n) [default: n]
|
||||
Does your BSP have a keyboard? (y/n) [default: y]
|
||||
3) standard/default/arm-versatile-926ejs
|
||||
4) standard/default/base
|
||||
5) standard/default/beagleboard
|
||||
6) standard/default/cedartrailbsp (copy).xml
|
||||
7) standard/default/common-pc-64/base
|
||||
8) standard/default/common-pc-64/jasperforest
|
||||
9) standard/default/common-pc-64/romley
|
||||
10) standard/default/common-pc-64/sugarbay
|
||||
11) standard/default/common-pc/atom-pc
|
||||
12) standard/default/common-pc/base
|
||||
13) standard/default/crownbay
|
||||
14) standard/default/emenlow
|
||||
15) standard/default/fishriver
|
||||
16) standard/default/fri2
|
||||
17) standard/default/fsl-mpc8315e-rdb
|
||||
18) standard/default/mti-malta32-be
|
||||
19) standard/default/mti-malta32-le
|
||||
20) standard/default/preempt-rt
|
||||
21) standard/default/qemu-ppc32
|
||||
22) standard/default/routerstationpro
|
||||
23) standard/preempt-rt/base
|
||||
24) standard/preempt-rt/qemu-ppc32
|
||||
25) standard/preempt-rt/routerstationpro
|
||||
26) standard/tiny
|
||||
3
|
||||
Do you need SMP support? (Y/n)
|
||||
Does your BSP have a touchscreen? (y/N)
|
||||
Does your BSP have a keyboard? (Y/n)
|
||||
New qemu BSP created in meta-myarm
|
||||
</literallayout>
|
||||
Let's take a closer look at the example now:
|
||||
@@ -1254,10 +1276,10 @@
|
||||
In the example, we use the <filename>arm</filename> architecture.
|
||||
</para></listitem>
|
||||
<listitem><para>The script then prompts you for the kernel.
|
||||
The default 3.4 kernel is acceptable.
|
||||
The default kernel is 3.2 and is acceptable.
|
||||
So, the example accepts the default.
|
||||
If you enter 'n', the script prompts you to further enter the kernel
|
||||
you do want to use (e.g. 3.0, 3.2_preempt-rt, and so forth.).</para></listitem>
|
||||
you do want to use (e.g. 3.0, 3.2_preempt-rt, etc.).</para></listitem>
|
||||
<listitem><para>Next, the script asks whether you would like to have a new
|
||||
branch created especially for your BSP in the local
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#local-kernel-files'>Linux Yocto Kernel</ulink>
|
||||
@@ -1270,20 +1292,25 @@
|
||||
The reason a new branch is the default is that typically
|
||||
new BSPs do require BSP-specific patches.
|
||||
The tool thus assumes that most of time a new branch is required.
|
||||
</para></listitem>
|
||||
<listitem><para>Regardless of which choice you make in the previous step,
|
||||
<note>In the current implementation, creation or re-use of a branch does
|
||||
not actually matter.
|
||||
The reason is because the generated BSPs assume that patches and
|
||||
configurations live in recipe-space, which is something that can be done
|
||||
with or without a dedicated branch.
|
||||
Generated BSPs, however, are different.
|
||||
This difference becomes significant once the tool's 'publish' functionality
|
||||
is implemented.</note></para></listitem>
|
||||
<listitem><para>Regardless of which choice is made in the previous step,
|
||||
you are now given the opportunity to select a particular machine branch on
|
||||
which to base your new BSP-specific machine branch
|
||||
which to base your new BSP-specific machine branch on
|
||||
(or to re-use if you had elected to not create a new branch).
|
||||
Because this example is generating an <filename>arm</filename> BSP, the example
|
||||
uses <filename>#1</filename> at the prompt, which selects the arm-versatile branch.
|
||||
uses <filename>#3</filename> at the prompt, which selects the arm-versatile branch.
|
||||
</para></listitem>
|
||||
<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
|
||||
current working directory of the
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#source-directory'>Source Directory</ulink>,
|
||||
which is <filename>poky</filename> in this case.
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;#build-directory'>build directory</ulink>.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
@@ -1296,7 +1323,6 @@
|
||||
BBLAYERS = " \
|
||||
/usr/local/src/yocto/meta \
|
||||
/usr/local/src/yocto/meta-yocto \
|
||||
/usr/local/src/yocto/meta-yocto-bsp \
|
||||
/usr/local/src/yocto/meta-myarm \
|
||||
"
|
||||
</literallayout>
|
||||
@@ -1328,28 +1354,21 @@
|
||||
is to use the <filename>yocto-kernel</filename> built-in help as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ yocto-kernel
|
||||
Usage:
|
||||
Usage:
|
||||
|
||||
Modify and list Yocto BSP kernel config items and patches.
|
||||
Modify and list Yocto BSP kernel config items and patches.
|
||||
|
||||
usage: yocto-kernel [--version] [--help] COMMAND [ARGS]
|
||||
usage: yocto-kernel [--version] [--help] COMMAND [ARGS]
|
||||
|
||||
Current 'yocto-kernel' commands are:
|
||||
config list List the modifiable set of bare kernel config options for a BSP
|
||||
config add Add or modify bare kernel config options for a BSP
|
||||
config rm Remove bare kernel config options from a BSP
|
||||
patch list List the patches associated with a BSP
|
||||
patch add Patch the Yocto kernel for a BSP
|
||||
patch rm Remove patches from a BSP
|
||||
The most commonly used 'yocto-kernel' commands are:
|
||||
config list List the modifiable set of bare kernel config options for a BSP
|
||||
config add Add or modify bare kernel config options for a BSP
|
||||
config rm Remove bare kernel config options from a BSP
|
||||
patch list List the patches associated with a BSP
|
||||
patch add Patch the Yocto kernel for a BSP
|
||||
patch rm Remove patches from a BSP
|
||||
|
||||
See 'yocto-kernel help COMMAND' for more information on a specific command.
|
||||
|
||||
|
||||
|
||||
Options:
|
||||
--version show program's version number and exit
|
||||
-h, --help show this help message and exit
|
||||
-D, --debug output debug information
|
||||
See 'yocto-kernel help COMMAND' for more information on a specific command.
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 17 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;
|
||||
}
|
||||
|
||||
715
documentation/dev-manual/dev-manual-bsp-appendix.xml
Normal file
@@ -0,0 +1,715 @@
|
||||
<!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; ] >
|
||||
|
||||
<appendix id='dev-manual-bsp-appendix'>
|
||||
|
||||
<title>BSP Development Example</title>
|
||||
|
||||
<para>
|
||||
This appendix provides a complete BSP development example.
|
||||
The example assumes the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>No previous preparation or use of the Yocto Project.</para></listitem>
|
||||
<listitem><para>Use of the Crown Bay Board Support Package (BSP) as a "base" BSP from
|
||||
which to work.
|
||||
The example begins with the Crown Bay BSP as the starting point
|
||||
but ends by building a new 'atom-pc' BSP, which was based on the Crown Bay BSP.
|
||||
</para></listitem>
|
||||
<listitem><para>Shell commands assume <filename>bash</filename></para></listitem>
|
||||
<listitem><para>Example was developed on an Intel-based Core i7 platform running
|
||||
Ubuntu 10.04 LTS released in April of 2010.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<section id='getting-local-yocto-project-files-and-bsp-files'>
|
||||
<title>Getting Local Source 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.
|
||||
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
|
||||
<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>:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/poky
|
||||
$ 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
|
||||
<filename>&YOCTO_POKY;</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ tar xfj &YOCTO_POKY_TARBALL;
|
||||
$ cd &YOCTO_POKY;
|
||||
</literallayout>
|
||||
<note><para>If you're using the tarball method, you can ignore all the following steps that
|
||||
ask you to carry out Git operations.
|
||||
You already have the results of those operations
|
||||
in the form of the &DISTRO_NAME; release tarballs.
|
||||
Consequently, there is nothing left to do other than extract those tarballs into the
|
||||
proper locations.</para>
|
||||
|
||||
<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.
|
||||
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.
|
||||
See the
|
||||
"<link linkend='repositories-tags-and-branches'>Repositories, Tags, and Branches</link>" section
|
||||
for more discussion around these differences.</para></note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
With the local <filename>poky</filename> Git repository set up,
|
||||
you have all the development branches available to you from which you can work.
|
||||
Next, you need to be sure that your local repository reflects the exact
|
||||
release in which you are interested.
|
||||
From inside the repository you can see the development branches that represent
|
||||
areas of development that have diverged from the main (master) branch
|
||||
at some point, such as a branch to track a maintenance release's development.
|
||||
You can also see the tag names used to mark snapshots of stable releases or
|
||||
points in the repository.
|
||||
Use the following commands to list out the branches and the tags in the repository,
|
||||
respectively.
|
||||
<literallayout class='monospaced'>
|
||||
$ git branch -a
|
||||
$ git tag -l
|
||||
</literallayout>
|
||||
For this example, we are going to use the Yocto Project &DISTRO; Release, which is code
|
||||
named "&DISTRO_NAME;".
|
||||
To make sure we have a local area (branch in Git terms) on our machine that
|
||||
reflects the &DISTRO; release, we can use the following commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ git fetch --tags
|
||||
$ git checkout &DISTRO_NAME;-&POKYVERSION; -b &DISTRO_NAME;
|
||||
Switched to a new branch '&DISTRO_NAME;'
|
||||
</literallayout>
|
||||
The <filename>git fetch --tags</filename> is somewhat redundant since you just set
|
||||
up the repository and should have all the tags.
|
||||
The <filename>fetch</filename> command makes sure all the tags are available in your
|
||||
local repository.
|
||||
The Git <filename>checkout</filename> command with the <filename>-b</filename> option
|
||||
creates a local branch for you named <filename>&DISTRO_NAME;</filename>.
|
||||
Your local branch begins in the same state as the Yocto Project &DISTRO; released tarball
|
||||
marked with the <filename>&DISTRO_NAME;-&POKYVERSION;</filename> tag in the source repositories.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='choosing-a-base-bsp-app'>
|
||||
<title>Choosing a Base BSP</title>
|
||||
|
||||
<para>
|
||||
For this example, the base BSP is the <trademark class='registered'>Intel</trademark>
|
||||
<trademark class='trade'>Atom</trademark> Processor E660 with Intel Platform
|
||||
Controller Hub EG20T Development Kit, which is otherwise referred to as "Crown Bay."
|
||||
The BSP layer is <filename>meta-crownbay</filename>.
|
||||
The base BSP is simply the BSP
|
||||
we will be using as a starting point, so don't worry if you don't actually have Crown Bay
|
||||
hardware.
|
||||
The remainder of the example transforms the base BSP into a BSP that should be
|
||||
able to boot on generic atom-pc (netbook) hardware.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For information on how to choose a base BSP, see
|
||||
"<link linkend='developing-a-board-support-package-bsp'>Developing a Board Support Package (BSP)</link>".
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='getting-your-base-bsp-app'>
|
||||
<title>Getting Your Base BSP</title>
|
||||
|
||||
<para>
|
||||
You need to have the base BSP layer on your development system.
|
||||
Similar to the local <link linkend='source-directory'>source directory</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.
|
||||
See "<link linkend='getting-setup'>Getting Setup</link>" for information on how to get
|
||||
the BSP files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This example assumes the BSP layer will be located within a directory named
|
||||
<filename>meta-intel</filename> contained within the <filename>poky</filename>
|
||||
parent directory.
|
||||
The following steps will automatically create the
|
||||
<filename>meta-intel</filename> directory and the contained
|
||||
<filename>meta-crownbay</filename> starting point in both the Git and the tarball cases.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you're using the Git method, you could do the following to create
|
||||
the starting layout after you have made sure you are in the <filename>poky</filename>
|
||||
directory created in the previous steps:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone git://git.yoctoproject.org/meta-intel.git
|
||||
$ cd meta-intel
|
||||
</literallayout>
|
||||
Alternatively, you can start with the downloaded Crown Bay tarball.
|
||||
You can download the &DISTRO_NAME; version of the BSP tarball from the
|
||||
<ulink url='&YOCTO_HOME_URL;/download'>Download</ulink> page of the
|
||||
Yocto Project website.
|
||||
Here is the specific link for the tarball needed for this example:
|
||||
<ulink url='&YOCTO_MACHINES_DL_URL;/crownbay-noemgd/crownbay-noemgd-&DISTRO_NAME;-&POKYVERSION;.tar.bz2'></ulink>.
|
||||
Again, be sure that you are already in the <filename>poky</filename> directory
|
||||
as described previously before installing the tarball:
|
||||
<literallayout class='monospaced'>
|
||||
$ tar xfj crownbay-noemgd-&DISTRO_NAME;-&POKYVERSION;.tar.bz2
|
||||
$ cd meta-intel
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>meta-intel</filename> directory contains all the metadata
|
||||
that supports BSP creation.
|
||||
If you're using the Git method, the following
|
||||
step will switch to the &DISTRO_NAME; metadata.
|
||||
If you're using the tarball method, you already have the correct metadata and can
|
||||
skip to the next step.
|
||||
Because <filename>meta-intel</filename> is its own Git repository, you will want
|
||||
to be sure you are in the appropriate branch for your work.
|
||||
For this example we are going to use the <filename>&DISTRO_NAME;</filename> branch.
|
||||
<literallayout class='monospaced'>
|
||||
$ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME;
|
||||
Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin.
|
||||
Switched to a new branch '&DISTRO_NAME;'
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='making-a-copy-of-the-base bsp-to-create-your-new-bsp-layer-app'>
|
||||
<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.
|
||||
To create your BSP layer, you simply copy the <filename>meta-crownbay</filename>
|
||||
layer to a new layer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For this example, the new layer will be named <filename>meta-mymachine</filename>.
|
||||
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.
|
||||
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'>
|
||||
$ cp -a meta-crownbay/ meta-mymachine
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='making-changes-to-your-bsp-app'>
|
||||
<title>Making Changes to Your BSP</title>
|
||||
|
||||
<para>
|
||||
Right now you have two identical BSP layers with different names:
|
||||
<filename>meta-crownbay</filename> and <filename>meta-mymachine</filename>.
|
||||
You need to change your configurations so that they work for your new BSP and
|
||||
your particular hardware.
|
||||
The following sections look at each of these areas of the BSP.
|
||||
</para>
|
||||
|
||||
<section id='changing-the-bsp-configuration'>
|
||||
<title>Changing the BSP Configuration</title>
|
||||
|
||||
<para>
|
||||
We will look first at the configurations, which are all done in the layer’s
|
||||
<filename>conf</filename> directory.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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
|
||||
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>.
|
||||
<literallayout class='monospaced'>
|
||||
$ rm meta-mymachine/conf/machine/crownbay.conf
|
||||
$ mv meta-mymachine/conf/machine/crownbay-noemgd.conf \
|
||||
meta-mymachine/conf/machine/mymachine.conf
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, we need to make changes to the <filename>mymachine.conf</filename> itself.
|
||||
The only changes we want to make for this example are to the comment lines.
|
||||
Changing comments, of course, is never strictly necessary, but it's alway good form to make
|
||||
them reflect reality as much as possible.
|
||||
|
||||
Here, simply substitute the Crown Bay name with an appropriate name for the BSP
|
||||
(<filename>mymachine</filename> in this case) and change the description to
|
||||
something that describes your hardware.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that inside the <filename>mymachine.conf</filename> is the
|
||||
<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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The next configuration file in the new BSP layer we need to edit is
|
||||
<filename>meta-mymachine/conf/layer.conf</filename>.
|
||||
This file identifies build information needed for the new layer.
|
||||
You can see the
|
||||
"<ulink url='&YOCTO_DOCS_BSP_URL;#bsp-filelayout-layer'>Layer Configuration File</ulink>" section
|
||||
in The Board Support Packages (BSP) Development Guide for more information on this configuration file.
|
||||
Basically, we are changing the existing statements to work with our BSP.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The file contains these statements that reference the Crown Bay BSP:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILE_COLLECTIONS += "crownbay"
|
||||
BBFILE_PATTERN_crownbay := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_crownbay = "6"
|
||||
|
||||
LAYERDEPENDS_crownbay = "intel"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Simply substitute the machine string name <filename>crownbay</filename>
|
||||
with the new machine name <filename>mymachine</filename> to get the following:
|
||||
<literallayout class='monospaced'>
|
||||
BBFILE_COLLECTIONS += "mymachine"
|
||||
BBFILE_PATTERN_mymachine := "^${LAYERDIR}/"
|
||||
BBFILE_PRIORITY_mymachine = "6"
|
||||
|
||||
LAYERDEPENDS_mymachine = "intel"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='changing-the-recipes-in-your-bsp'>
|
||||
<title>Changing the Recipes in Your BSP</title>
|
||||
|
||||
<para>
|
||||
Now we will take a look at the recipes in your new layer.
|
||||
The standard BSP structure has areas for BSP, graphics, core, and kernel recipes.
|
||||
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
|
||||
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>,
|
||||
<filename>recipes-core</filename>, and
|
||||
<filename>recipes-graphics</filename> directories.
|
||||
</para>
|
||||
|
||||
<section id='changing-recipes-bsp'>
|
||||
<title>Changing <filename>recipes-bsp</filename></title>
|
||||
|
||||
<para>
|
||||
First, let's look at <filename>recipes-bsp</filename>.
|
||||
For this example we are not adding any new BSP recipes.
|
||||
And, we only need to remove the formfactor we do not want and change the name of
|
||||
the remaining one that doesn't support EMGD.
|
||||
These commands take care of the <filename>recipes-bsp</filename> recipes:
|
||||
<literallayout class='monospaced'>
|
||||
$ rm -rf meta-mymachine/recipes-bsp/formfactor/formfactor/crownbay
|
||||
$ mv meta-mymachine/recipes-bsp/formfactor/formfactor/crownbay-noemgd/ \
|
||||
meta-mymachine/recipes-bsp/formfactor/formfactor/mymachine
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='changing-recipes-graphics'>
|
||||
<title>Changing <filename>recipes-graphics</filename></title>
|
||||
|
||||
<para>
|
||||
Now let's look at <filename>recipes-graphics</filename>.
|
||||
For this example we want to remove anything that supports EMGD and
|
||||
be sure to rename remaining directories appropriately.
|
||||
The following commands clean up the <filename>recipes-graphics</filename> directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ rm -rf meta-mymachine/recipes-graphics/xorg-xserver/xserver-xf86-config/crownbay
|
||||
$ mv meta-mymachine/recipes-graphics/xorg-xserver/xserver-xf86-config/crownbay-noemgd \
|
||||
meta-mymachine/recipes-graphics/xorg-xserver/xserver-xf86-config/mymachine
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
At this point the <filename>recipes-graphics</filename> directory just has files that
|
||||
support Video Electronics Standards Association (VESA) graphics modes and not EMGD.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='changing-recipes-core'>
|
||||
<title>Changing <filename>recipes-core</filename></title>
|
||||
|
||||
<para>
|
||||
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
|
||||
<filename>meta/recipes-core/tasks</filename>.
|
||||
The append file in our layer right now is Crown Bay-specific and supports
|
||||
EMGD and non-EMGD.
|
||||
Here are the contents of the file:
|
||||
<literallayout class='monospaced'>
|
||||
RRECOMMENDS_task-core-tools-profile_append_crownbay = " systemtap"
|
||||
RRECOMMENDS_task-core-tools-profile_append_crownbay-noemgd = " systemtap"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>RRECOMMENDS</filename> statements list packages that
|
||||
extend usability.
|
||||
The first <filename>RRECOMMENDS</filename> statement can be removed, while the
|
||||
second one can be changed to reflect <filename>meta-mymachine</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
RRECOMMENDS_task-core-tools-profile_append_mymachine = " systemtap"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='changing-recipes-kernel'>
|
||||
<title>Changing <filename>recipes-kernel</filename></title>
|
||||
|
||||
<para>
|
||||
Finally, let's look at <filename>recipes-kernel</filename> changes.
|
||||
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
|
||||
<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>
|
||||
statements point to the exact commits used by the Yocto Project development team
|
||||
in their source repositories that identify the right kernel for our hardware.
|
||||
In other words, the <filename>SRCREV</filename> values are simply Git commit
|
||||
IDs that identify which commit on each
|
||||
of the kernel branches (machine and meta) will be checked out and used to build
|
||||
the kernel.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
However, in the <filename>meta-mymachine</filename> layer in
|
||||
<filename>recipes-kernel/linux</filename> resides a <filename>.bbappend</filename>
|
||||
file named <filename>linux-yocto_3.2.bbappend</filename> that
|
||||
appends information to the recipe of the same name in <filename>meta/recipes-kernel/linux</filename>.
|
||||
Thus, the <filename>SRCREV</filename> statements in the append file override
|
||||
the more general statements found in <filename>meta</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The <filename>SRCREV</filename> statements in the append file currently identify
|
||||
the kernel that supports the Crown Bay BSP with and without EMGD support.
|
||||
Here are the statements:
|
||||
<note>The commit ID strings used in this manual might not match the actual commit
|
||||
ID strings found in the <filename>linux-yocto_3.2.bbappend</filename> file.
|
||||
For the example, this difference does not matter.</note>
|
||||
<literallayout class='monospaced'>
|
||||
SRCREV_machine_pn-linux-yocto_crownbay ?= \
|
||||
"211fc7f4d10ec2b82b424286aabbaff9254b7cbd"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay ?= \
|
||||
"514847185c78c07f52e02750fbe0a03ca3a31d8f"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_crownbay-noemgd ?= \
|
||||
"211fc7f4d10ec2b82b424286aabbaff9254b7cbd"
|
||||
SRCREV_meta_pn-linux-yocto_crownbay-noemgd ?= \
|
||||
"514847185c78c07f52e02750fbe0a03ca3a31d8f"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You will notice that there are two pairs of <filename>SRCREV</filename> statements.
|
||||
The top pair identifies the kernel that supports
|
||||
EMGD, which we don’t care about in this example.
|
||||
The bottom pair identifies the kernel that we will use:
|
||||
<filename>linux-yocto</filename>.
|
||||
At this point though, the unique commit strings all are still associated with
|
||||
Crown Bay and not <filename>meta-mymachine</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To fix this situation in <filename>linux-yocto_3.2.bbappend</filename>,
|
||||
we delete the two <filename>SRCREV</filename> statements that support
|
||||
EMGD (the top pair).
|
||||
We also change the remaining pair to specify <filename>mymachine</filename>
|
||||
and insert the commit identifiers to identify the kernel in which we
|
||||
are interested, which will be based on the <filename>atom-pc-standard</filename>
|
||||
kernel.
|
||||
In this case, because we're working with the &DISTRO_NAME; branch of everything, we
|
||||
need to use the <filename>SRCREV</filename> values for the atom-pc branch
|
||||
that are associated with the &DISTRO_NAME; release.
|
||||
To find those values, we need to find the <filename>SRCREV</filename>
|
||||
values that &DISTRO_NAME; uses for the atom-pc branch, which we find in the
|
||||
<filename>poky/meta-yocto/recipes-kernel/linux/linux-yocto_3.2.bbappend</filename>
|
||||
file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The machine <filename>SRCREV</filename> we want is in the
|
||||
<filename>SRCREV_machine_atom-pc</filename> variable.
|
||||
The meta <filename>SRCREV</filename> isn't specified in this file, so it must be
|
||||
specified in the base kernel recipe in the
|
||||
<filename>poky/meta/recipes-kernel/linux/linux-yocto_3.2.bb</filename>
|
||||
file, in the <filename>SRCREV_meta</filename> variable found there.
|
||||
Here are the final <filename>SRCREV</filename> statements:
|
||||
<literallayout class='monospaced'>
|
||||
SRCREV_machine_pn-linux-yocto_mymachine ?= \
|
||||
"f29531a41df15d74be5ad47d958e4117ca9e489e"
|
||||
SRCREV_meta_pn-linux-yocto_mymachine ?= \
|
||||
"b14a08f5c7b469a5077c10942f4e1aec171faa9d"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In this example, we're using the <filename>SRCREV</filename> values we
|
||||
found already captured in the &DISTRO_NAME; release because we're creating a BSP based on
|
||||
&DISTRO_NAME;.
|
||||
If, instead, we had based our BSP on the master branches, we would want to use
|
||||
the most recent <filename>SRCREV</filename> values taken directly from the kernel repo.
|
||||
We will not be doing that for this example.
|
||||
However, if you do base a future BSP on master and
|
||||
if you are familiar with Git repositories, you probably won’t have trouble locating the
|
||||
exact commit strings in the Yocto Project source repositories you need to change
|
||||
the <filename>SRCREV</filename> statements.
|
||||
You can find all the <filename>machine</filename> and <filename>meta</filename>
|
||||
branch points (commits) for the <filename>linux-yocto-3.2</filename> kernel at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit/cgit.cgi/linux-yocto-3.2'></ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you need a little more assistance after going to the link then do the following:
|
||||
<orderedlist>
|
||||
<listitem><para>Expand the list of branches by clicking <filename>[…]</filename></para></listitem>
|
||||
<listitem><para>Click on the <filename>standard/default/common-pc/atom-pc</filename>
|
||||
branch</para></listitem>
|
||||
<listitem><para>Click on the commit column header to view the top commit</para></listitem>
|
||||
<listitem><para>Copy the commit string for use in the
|
||||
<filename>linux-yocto_3.2.bbappend</filename> file</para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For the <filename>SRCREV</filename> statement that points to the <filename>meta</filename>
|
||||
branch use the same procedure except expand the <filename>meta</filename>
|
||||
branch in step 2 above.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Also in the <filename>linux-yocto_3.2.bbappend</filename> file are
|
||||
<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
|
||||
<filename>crownbay-noemgd</filename> and <filename>crownbay</filename>.
|
||||
Because we are using the <filename>atom-pc</filename> branch for this new BSP, we can also find
|
||||
the exact branch we need for the <filename>KMACHINE</filename>
|
||||
and <filename>KBRANCH</filename> variables in our new BSP from the value
|
||||
we find in the
|
||||
<filename>poky/meta-yocto/recipes-kernel/linux/linux-yocto_3.2.bbappend</filename>
|
||||
file we looked at in a previous step.
|
||||
In this case, the values we want are in the <filename>KMACHINE_atom-pc</filename> variable
|
||||
and the <filename>KBRANCH_atom-pc</filename> variables in that file.
|
||||
Here is the final <filename>linux-yocto_3.2.bbappend</filename> file after all
|
||||
the edits:
|
||||
<literallayout class='monospaced'>
|
||||
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
|
||||
|
||||
COMPATIBLE_MACHINE_mymachine = "mymachine"
|
||||
KMACHINE_mymachine = "atom-pc"
|
||||
KBRANCH_mymachine = "standard/default/common-pc/atom-pc"
|
||||
|
||||
SRCREV_machine_pn-linux-yocto_mymachine ?= \
|
||||
"f29531a41df15d74be5ad47d958e4117ca9e489e"
|
||||
SRCREV_meta_pn-linux-yocto_mymachine ?= \
|
||||
"b14a08f5c7b469a5077c10942f4e1aec171faa9d"
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='bsp-recipe-change-summary'>
|
||||
<title>BSP Recipe Change Summary</title>
|
||||
|
||||
<para>
|
||||
In summary, the edits to the layer’s recipe files result in removal of any files and
|
||||
statements that do not support your targeted hardware in addition to the inclusion
|
||||
of any new recipes you might need.
|
||||
In this example, it was simply a matter of ridding the new layer
|
||||
<filename>meta-mymachine</filename> of any code that supported the EMGD features
|
||||
and making sure we were identifying the kernel that supports our example, which
|
||||
is the <filename>atom-pc-standard</filename> kernel.
|
||||
We did not introduce any new recipes to the layer.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally, it is also important to update the layer’s <filename>README</filename>
|
||||
file so that the information in it reflects your BSP.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='preparing-for-the-build-app'>
|
||||
<title>Preparing for the Build</title>
|
||||
|
||||
<para>
|
||||
To get ready to build your image that uses the new layer you need to do the following:
|
||||
<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 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
|
||||
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.
|
||||
If you do not provide a name for the build directory it defaults to
|
||||
<filename>build</filename>.
|
||||
The <filename>yocto-build</filename> directory contains a
|
||||
<filename>conf</filename> directory that has
|
||||
two configuration files you will need to check: <filename>bblayers.conf</filename>
|
||||
and <filename>local.conf</filename>.</para></listitem>
|
||||
<listitem><para>Check and edit the resulting <filename>local.conf</filename> file.
|
||||
This file minimally identifies the machine for which to build the image by
|
||||
configuring the <filename>MACHINE</filename> variable.
|
||||
For this example you must set the variable to mymachine as follows:
|
||||
<literallayout class='monospaced'>
|
||||
MACHINE ??= “mymachine”
|
||||
</literallayout>
|
||||
You should also be sure any other variables in which you are interested are set.
|
||||
Some variables to consider are <filename>BB_NUMBER_THREADS</filename>
|
||||
and <filename>PARALLEL_MAKE</filename>, both of which can greatly reduce your build time
|
||||
if your development system supports multiple cores.
|
||||
For development systems that support multiple cores, a good rule of thumb is to set
|
||||
both the <filename>BB_NUMBER_THREADS</filename> and <filename>PARALLEL_MAKE</filename>
|
||||
variables to twice the number of cores your system supports.</para></listitem>
|
||||
<listitem><para>Update the <filename>bblayers.conf</filename> file so that it includes
|
||||
both the path to your new BSP layer and the path to the
|
||||
<filename>meta-intel</filename> layer.
|
||||
In this example, you need to include both these paths as part of the
|
||||
<filename>BBLAYERS</filename> variable:
|
||||
<literallayout class='monospaced'>
|
||||
$HOME/poky/meta-intel
|
||||
$HOME/poky/meta-intel/meta-mymachine
|
||||
</literallayout></para></listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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>
|
||||
|
||||
<section id='building-the-image-app'>
|
||||
<title>Building and Booting the Image</title>
|
||||
|
||||
<para>
|
||||
To build the image for our <filename>meta-mymachine</filename> BSP enter the following command
|
||||
from the same shell from which you ran the setup script.
|
||||
You should run the <filename>bitbake</filename> command without any intervening shell commands.
|
||||
For example, moving your working directory around could cause problems.
|
||||
Here is the command for this example:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -k core-image-sato
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This command specifies an image that has Sato support and that can be run from a USB device or
|
||||
from a CD without having to first install anything.
|
||||
The build process takes significant time and includes thousands of tasks, which are reported
|
||||
at the console.
|
||||
If the build results in any type of error you should check for misspellings in the
|
||||
files you changed or problems with your host development environment such as missing packages.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally, once you have an image, you can try booting it from a device
|
||||
(e.g. a USB device).
|
||||
To prepare a bootable USB device, insert a USB flash drive into your build system and
|
||||
copy the <filename>.hddimg</filename> file, located in the
|
||||
<filename>poky/build/tmp/deploy/images</filename>
|
||||
directory after a successful build to the flash drive.
|
||||
Assuming the USB flash drive takes device <filename>/dev/sdf</filename>,
|
||||
use <filename>dd</filename> to copy the live image to it.
|
||||
For example:
|
||||
<literallayout class='monospaced'>
|
||||
# dd if=core-image-sato-mymachine-20111101223904.hddimg of=/dev/sdf
|
||||
# sync
|
||||
# eject /dev/sdf
|
||||
</literallayout>
|
||||
You should now have a bootable USB flash device.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Insert the device
|
||||
into a bootable USB socket on the target, and power it on.
|
||||
The system should boot to the Sato graphical desktop.
|
||||
<footnote><para>Because
|
||||
this new image is not in any way tailored to the system you're
|
||||
booting it on, which is assumed to be some sort of atom-pc (netbook) system for this
|
||||
example, it might not be completely functional though it should at least boot to a text
|
||||
prompt.
|
||||
Specifically, it might fail to boot into graphics without some tweaking.
|
||||
If this ends up being the case, a possible next step would be to replace the
|
||||
<filename>mymachine.conf</filename>
|
||||
contents with the contents of <filename>atom-pc.conf</filename> and replace
|
||||
<filename>xorg.conf</filename> with <filename>atom-pc xorg.conf</filename>
|
||||
in <filename>meta-yocto</filename> and see if it fares any better.
|
||||
In any case, following the previous steps will give you a buildable image that
|
||||
will probably boot on most systems.
|
||||
Getting things working like you want
|
||||
them to for your hardware will normally require some amount of experimentation with
|
||||
configuration settings.</para></footnote>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For reference, the sato image produced by the previous steps for &DISTRO_NAME;
|
||||
should look like the following in terms of size.
|
||||
If your sato image is much different from this,
|
||||
you probably made a mistake in one of the above steps:
|
||||
<literallayout class='monospaced'>
|
||||
260538368 2012-04-27 01:44 core-image-sato-mymachine-20120427025051.hddimg
|
||||
</literallayout>
|
||||
<note>The previous instructions are also present in the README that was copied
|
||||
from meta-crownbay, which should also be updated to reflect the specifics of your
|
||||
new BSP.
|
||||
That file and the <filename>README.hardware</filename> file in the top-level
|
||||
<filename>poky</filename> directory
|
||||
also provides some suggestions for things to try if booting fails and produces
|
||||
strange error messages.</note>
|
||||
</para>
|
||||
</section>
|
||||
</appendix>
|
||||
|
||||
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
@@ -23,9 +23,9 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Yocto Project Development Manual, however, does provide detailed examples
|
||||
on how to change the kernel source code, reconfigure the kernel, and develop
|
||||
an application using the popular <trademark class='trade'>Eclipse</trademark> IDE.
|
||||
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.
|
||||
You can find this information in the appendices of the manual.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<listitem><para>Development case overviews for both system development and user-space
|
||||
applications.</para></listitem>
|
||||
<listitem><para>An overview and understanding of the emulation environment used with
|
||||
the Yocto Project - the Quick EMUlator (QEMU).</para></listitem>
|
||||
the Yocto Project (QEMU).</para></listitem>
|
||||
<listitem><para>An understanding of basic kernel architecture and concepts.</para></listitem>
|
||||
<listitem><para>Many references to other sources of related information.</para></listitem>
|
||||
</itemizedlist>
|
||||
@@ -59,14 +59,14 @@
|
||||
<itemizedlist>
|
||||
<listitem><para>Step-by-step instructions if those instructions exist in other Yocto
|
||||
Project documentation.
|
||||
For example, the Yocto Project Application Developer's Guide contains detailed
|
||||
instruction on how to run the
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;#installing-the-adt'>Installing the ADT and Toolchains</ulink>,
|
||||
which is used to set up a cross-development environment.</para></listitem>
|
||||
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.
|
||||
This type of material resides in an appropriate reference manual.
|
||||
For example, system variables are documented in the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;'>Yocto Project Reference Manual</ulink>.</para></listitem>
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;'>
|
||||
Yocto Project Reference Manual</ulink>.</para></listitem>
|
||||
<listitem><para>Detailed public information that is not specific to the Yocto Project.
|
||||
For example, exhaustive information on how to use Git is covered better through the
|
||||
Internet than in this manual.</para></listitem>
|
||||
@@ -86,24 +86,28 @@
|
||||
</emphasis> The home page for the Yocto Project provides lots of information on the project
|
||||
as well as links to software and documentation.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;'>Yocto Project Quick Start</ulink>:</emphasis> This short document lets you get started
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;'>
|
||||
The Yocto Project Quick Start</ulink>:</emphasis> This short document lets you get started
|
||||
with the Yocto Project quickly and start building an image.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;'>Yocto Project Reference Manual</ulink>:</emphasis> This manual is a reference
|
||||
<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."
|
||||
The manual also contains a reference chapter on Board Support Package (BSP)
|
||||
layout.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>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
|
||||
<ulink url='&YOCTO_DOCS_ADT_URL;'>
|
||||
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;'>Yocto Project Board Support Package (BSP) Developer's Guide</ulink>:</emphasis>
|
||||
<ulink url='&YOCTO_DOCS_BSP_URL;'>
|
||||
The Yocto Project Board Support Package (BSP) Developer's Guide</ulink>:</emphasis>
|
||||
This guide defines the structure for BSP components.
|
||||
Having a commonly understood structure encourages standardization.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_DOCS_KERNEL_URL;'>Yocto Project Kernel Architecture and Use Manual</ulink>:</emphasis>
|
||||
<ulink url='&YOCTO_DOCS_KERNEL_URL;'>
|
||||
The Yocto Project Kernel Architecture and Use Manual</ulink>:</emphasis>
|
||||
This manual describes the architecture of the Yocto Project kernel and provides
|
||||
some work flow examples.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
@@ -115,7 +119,7 @@
|
||||
<ulink url='&YOCTO_WIKI_URL;/wiki/FAQ'>FAQ</ulink>:</emphasis>
|
||||
A list of commonly asked questions and their answers.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='&YOCTO_HOME_URL;/download/yocto/yocto-project-&DISTRO;-release-notes-poky-&POKYVERSION;'>
|
||||
<ulink url='&YOCTO_HOME_URL;/download/yocto/yocto-project-1.1-release-notes-poky-&POKYVERSION;'>
|
||||
Release Notes</ulink>:</emphasis> Features, updates and known issues for the current
|
||||
release of the Yocto Project.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
@@ -167,16 +171,18 @@
|
||||
Project derives its build system (Poky) 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
|
||||
BitBake</ulink>:</emphasis> The tool used by the OpenEmbedded build systm
|
||||
to process project metadata.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
BitBake User Manual:</emphasis>
|
||||
A comprehensive guide to the BitBake tool.
|
||||
If you want information on BitBake, see the user manual inculded in the
|
||||
<filename>bitbake/doc/manual</filename> directory of the
|
||||
<link linkend='source-directory'>Source Directory</link>.</para></listitem>
|
||||
<ulink url='http://bitbake.berlios.de/manual/'>
|
||||
BitBake User Manual</ulink>:</emphasis> A comprehensive guide to the BitBake tool.
|
||||
</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='http://wiki.qemu.org/Index.html'>Quick EMUlator (QEMU)</ulink>:
|
||||
<ulink url='http://pimlico-project.org/'>Pimlico</ulink>:</emphasis>
|
||||
A suite of lightweight Personal Information Management (PIM) applications designed
|
||||
primarily for handheld and mobile devices.</para></listitem>
|
||||
<listitem><para><emphasis>
|
||||
<ulink url='http://wiki.qemu.org/Index.html'>QEMU</ulink>:
|
||||
</emphasis> An open-source machine emulator and virtualizer.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
@@ -12,13 +12,6 @@
|
||||
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.
|
||||
<note>
|
||||
You can use the <filename>yocto-kernel</filename> script
|
||||
found in the <link linkend='source-directory'>Source Directory</link>
|
||||
under <filename>scripts</filename> to manage kernel patches and configuration.
|
||||
See the "<ulink url='&YOCTO_DOCS_BSP_URL;#managing-kernel-patches-and-config-items-with-yocto-kernel'>Managing kernel Patches and Config Items with yocto-kernel</ulink>"
|
||||
section in the Yocto Project Board Support Packages (BSP) Developer's Guide for
|
||||
more information.</note>
|
||||
</para>
|
||||
|
||||
<section id='modifying-the-kernel-source-code'>
|
||||
@@ -41,11 +34,11 @@
|
||||
Briefly, you need the following:
|
||||
<itemizedlist>
|
||||
<listitem><para>A local
|
||||
<link linkend='source-directory'>Source Directory</link> for the
|
||||
<link linkend='source-directory'>source directory</link> for the
|
||||
poky Git repository</para></listitem>
|
||||
<listitem><para>Local copies of 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 source directory.</para></listitem>
|
||||
<listitem><para>A bare clone of the
|
||||
<link linkend='local-kernel-files'>Yocto Project Kernel</link> upstream Git
|
||||
repository to which you want to push your modifications.
|
||||
@@ -66,7 +59,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<imagedata fileref="figures/kernel-example-repos-generic.png" width="7in" depth="5in"
|
||||
<imagedata fileref="figures/kernel-example-repos-denzil.png" width="7in" depth="5in"
|
||||
align="center" scale="100" />
|
||||
</para>
|
||||
|
||||
@@ -76,18 +69,16 @@
|
||||
<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
|
||||
<link linkend='source-directory'>Source Directory</link> also
|
||||
contains the
|
||||
<link linkend='build-directory'>Build Directory</link>,
|
||||
which contains the configuration directory
|
||||
In this example, the source directory 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
|
||||
Also in this example, the source directory contains local copies of 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>
|
||||
<listitem><para><emphasis>Local copies of the<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
|
||||
@@ -134,19 +125,17 @@
|
||||
<title>Setting Up the Local Source Directory</title>
|
||||
|
||||
<para>
|
||||
You can set up the
|
||||
<link linkend='source-directory'>Source Directory</link>
|
||||
through tarball extraction or by
|
||||
You can set up the source directory 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 source directory.
|
||||
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 source directory 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:
|
||||
@@ -172,7 +161,7 @@
|
||||
|
||||
<para>
|
||||
This example creates a local copy of the <filename>poky-extras</filename> Git
|
||||
repository inside the <filename>poky</filename> Source Directory.
|
||||
repository inside the <filename>poky</filename> source directory.
|
||||
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
|
||||
@@ -183,12 +172,11 @@
|
||||
Because this example uses the Yocto Project &DISTRO; Release code
|
||||
named "&DISTRO_NAME;", which maps to the <filename>&DISTRO_NAME;</filename>
|
||||
branch in the repository, you need to be sure you are using that
|
||||
branch for <filename>poky-extras</filename>.
|
||||
branch for <filename>poky-extra</filename>.
|
||||
The following commands create and checkout the local
|
||||
branch you are using for the <filename>&DISTRO_NAME;</filename>
|
||||
branch:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky/poky-extras
|
||||
$ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME;
|
||||
Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin.
|
||||
Switched to a new branch '&DISTRO_NAME;'
|
||||
@@ -200,7 +188,7 @@
|
||||
<title>Setting Up the Bare Clone and its Copy</title>
|
||||
|
||||
<para>
|
||||
This example modifies the <filename>linux-yocto-3.4</filename> kernel.
|
||||
This example modifies the <filename>linux-yocto-3.2</filename> kernel.
|
||||
Thus, you need to create a bare clone of that kernel and then make a copy of the
|
||||
bare clone.
|
||||
See the bulleted item
|
||||
@@ -212,16 +200,17 @@
|
||||
The bare clone exists for the kernel build tools and simply as the receiving end
|
||||
of <filename>git push</filename>
|
||||
commands after you make edits and commits inside the copy of the clone.
|
||||
The copy (<filename>my-linux-yocto-3.4-work</filename> in this example) has to have
|
||||
The copy (<filename>my-linux-yocto-3.2-work</filename> in this example) has to have
|
||||
a local branch created and checked out for your work.
|
||||
This example uses <filename>common-pc-base</filename> as the local branch.
|
||||
The following commands create and checkout the branch:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/my-linux-yocto-3.4-work
|
||||
$ git checkout -b standard-common-pc-base origin/standard/common-pc/base
|
||||
Branch standard-common-pc-base set up to track remote branch
|
||||
standard/common-pc/base from origin.
|
||||
Switched to a new branch 'standard-common-pc-base'
|
||||
$ cd ~/my-linux-yocto-3.2-work
|
||||
$ git checkout -b common-pc-base origin/standard/default/common-pc/base
|
||||
Checking out files: 100% (532/532), done.
|
||||
Branch common-pc-base set up to track remote branch
|
||||
standard/default/common-pc/base from origin.
|
||||
Switched to a new branch 'common-pc-base'
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
@@ -235,7 +224,7 @@
|
||||
<note>
|
||||
Because a full build can take hours, you should check two variables in the
|
||||
<filename>build</filename> directory that is created after you source the
|
||||
<filename>&OE_INIT_FILE;</filename> script.
|
||||
<filename>oe-init-build-env</filename> script.
|
||||
You can find these variables
|
||||
<filename>BB_NUMBER_THREADS</filename> and <filename>PARALLEL_MAKE</filename>
|
||||
in the <filename>build/conf</filename> directory in the
|
||||
@@ -253,36 +242,11 @@
|
||||
If necessary, the script creates the build directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source &OE_INIT_FILE;
|
||||
You had no conf/local.conf file. This configuration file has therefore been
|
||||
created for you with some default values. You may wish to edit it to use a
|
||||
different MACHINE (target hardware) or enable parallel build options to take
|
||||
advantage of multiple cores for example. See the file for more information as
|
||||
common configuration options are commented.
|
||||
$ source oe-init-build-env
|
||||
|
||||
The Yocto Project has extensive documentation about OE including a reference manual
|
||||
which can be found at:
|
||||
http://yoctoproject.org/documentation
|
||||
### Shell environment set up for builds. ###
|
||||
|
||||
For more information about OpenEmbedded see their website:
|
||||
http://www.openembedded.org/
|
||||
|
||||
You had no conf/bblayers.conf file. The configuration file has been created for
|
||||
you with some default values. To add additional metadata layers into your
|
||||
configuration please add entries to this file.
|
||||
|
||||
The Yocto Project has extensive documentation about OE including a reference manual
|
||||
which can be found at:
|
||||
http://yoctoproject.org/documentation
|
||||
|
||||
For more information about OpenEmbedded see their website:
|
||||
http://www.openembedded.org/
|
||||
|
||||
|
||||
|
||||
### Shell environment set up for builds. ###
|
||||
|
||||
You can now run 'bitbake <target>>'
|
||||
You can now run 'bitbake <target>'
|
||||
|
||||
Common targets are:
|
||||
core-image-minimal
|
||||
@@ -337,7 +301,7 @@
|
||||
|
||||
<para>
|
||||
The file you change in this example is named <filename>calibrate.c</filename>
|
||||
and is located in the <filename>my-linux-yocto-3.4-work</filename> Git repository
|
||||
and is located in the <filename>my-linux-yocto-3.2-work</filename> Git repository
|
||||
(the copy of the bare clone) in <filename>init</filename>.
|
||||
This example simply inserts several <filename>printk</filename> statements
|
||||
at the beginning of the <filename>calibrate_delay</filename> function.
|
||||
@@ -401,7 +365,7 @@
|
||||
<para>
|
||||
The following command pushes the changes to the bare clone:
|
||||
<literallayout class='monospaced'>
|
||||
$ git push origin standard-common-pc-base:standard/default/common-pc/base
|
||||
$ git push origin common-pc-base:standard/default/common-pc/base
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
@@ -456,25 +420,21 @@
|
||||
BBLAYERS = " \
|
||||
/home/scottrif/poky/meta \
|
||||
/home/scottrif/poky/meta-yocto \
|
||||
/home/scottrif/poky/meta-yocto-bsp \
|
||||
/home/scottrif/poky/poky-extras/meta-kernel-dev \
|
||||
"
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para><emphasis>Identify Your Source Files:</emphasis> In the
|
||||
<filename>linux-yocto_3.4.bbappend</filename> file located in the
|
||||
<filename>linux-yocto_3.2.bbappend</filename> file located in the
|
||||
<filename>poky-extras/meta-kernel-dev/recipes-kernel/linux</filename>
|
||||
directory, you need to identify the location of the
|
||||
local source code, which in this example is the bare clone named
|
||||
<filename>linux-yocto-3.4.git</filename>.
|
||||
<filename>linux-yocto-3.2.git</filename>.
|
||||
To do this, set the <filename>KSRC_linux_yocto</filename> variable to point to your
|
||||
local <filename>linux-yocto-3.4.git</filename> Git repository by adding the
|
||||
local <filename>linux-yocto-3.2.git</filename> Git repository by adding the
|
||||
following statement.
|
||||
Also, be sure the <filename>SRC_URI</filename> variable is pointing to
|
||||
your kernel source files by removing the comment.
|
||||
Finally, be sure to substitute your user information in the statement:
|
||||
Be sure to substitute your user information in the statement:
|
||||
<literallayout class='monospaced'>
|
||||
KSRC_linux_yocto_3_4 ?= "/home/scottrif/linux-yocto-3.4.git"
|
||||
SRC_URI = "git://${KSRC_linux_yocto_3_4};protocol=file;nocheckout=1;branch=${KBRANCH},meta;name=machine,meta"
|
||||
KSRC_linux_yocto_3_2 ?= "/home/scottrif/linux-yocto-3.2.git"
|
||||
</literallayout></para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
@@ -487,7 +447,7 @@
|
||||
comment out the <filename>COMPATIBLE_MACHINE</filename> statements in all
|
||||
unused <filename>.bbappend</filename> files, or simply remove (or rename) all the files
|
||||
except the one your are using for the build
|
||||
(i.e. <filename>linux-yocto_3.4.bbappend</filename> in this example).</para>
|
||||
(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
|
||||
@@ -504,11 +464,11 @@
|
||||
Do the following:
|
||||
<orderedlist>
|
||||
<listitem><para>Your environment should be set up since you previously sourced
|
||||
the <filename>&OE_INIT_FILE;</filename> script.
|
||||
the <filename>oe-init-build-env</filename> script.
|
||||
If it isn't, source the script again from <filename>poky</filename>.
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source &OE_INIT_FILE;
|
||||
$ source oe-init-build-env
|
||||
</literallayout>
|
||||
</para></listitem>
|
||||
<listitem><para>Be sure old images are cleaned out by running the
|
||||
@@ -546,6 +506,299 @@
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='changing-the-kernel-configuration'>
|
||||
<title>Changing the Kernel Configuration</title>
|
||||
|
||||
<para>
|
||||
This example changes the default behavior, which is "on", of the Symmetric
|
||||
Multi-processing Support (<filename>CONFIG_SMP</filename>) to "off".
|
||||
It is a simple example that demonstrates how to reconfigure the kernel.
|
||||
</para>
|
||||
|
||||
<section id='getting-set-up-to-run-this-example'>
|
||||
<title>Getting Set Up to Run this Example</title>
|
||||
|
||||
<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
|
||||
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
|
||||
<filename>CONFIG_SMP</filename> Behavior</link>", and continue with the
|
||||
example.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you don't have the source directory 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>.
|
||||
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,
|
||||
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:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd poky
|
||||
$ git branch -a
|
||||
$ git tag -l
|
||||
</literallayout>
|
||||
This example uses the Yocto Project &DISTRO; Release code named "&DISTRO_NAME;",
|
||||
which maps to the <filename>&DISTRO_NAME;</filename> branch in the repository.
|
||||
The following commands create and checkout the local <filename>&DISTRO_NAME;</filename>
|
||||
branch:
|
||||
<literallayout class='monospaced'>
|
||||
$ git checkout -b &DISTRO_NAME; origin/&DISTRO_NAME;
|
||||
Branch &DISTRO_NAME; set up to track remote branch &DISTRO_NAME; from origin.
|
||||
Switched to a new branch '&DISTRO_NAME;'
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Next, you need to build the default <filename>qemux86</filename> image that you
|
||||
can boot using QEMU.
|
||||
<note>
|
||||
Because a full build can take hours, you should check two variables in the
|
||||
<filename>build</filename> directory that is created after you source the
|
||||
<filename>oe-init-build-env</filename> script.
|
||||
You can find these variables
|
||||
<filename>BB_NUMBER_THREADS</filename> and <filename>PARALLEL_MAKE</filename>
|
||||
in the <filename>build/conf</filename> directory in the
|
||||
<filename>local.conf</filename> configuration file.
|
||||
By default, these variables are commented out.
|
||||
If your host development system supports multi-core and multi-thread capabilities,
|
||||
you can uncomment these statements and set the variables to significantly shorten
|
||||
the full build time.
|
||||
As a guideline, set <filename>BB_NUMBER_THREADS</filename> to twice the number
|
||||
of cores your machine supports and set <filename>PARALLEL_MAKE</filename> to one and
|
||||
a half times the number of cores your machine supports.
|
||||
</note>
|
||||
The following two commands <filename>source</filename> the build environment setup script
|
||||
and build the default <filename>qemux86</filename> image.
|
||||
If necessary, the script creates the build directory:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source oe-init-build-env
|
||||
|
||||
### Shell environment set up for builds. ###
|
||||
|
||||
You can now run 'bitbake <target>'
|
||||
|
||||
Common targets are:
|
||||
core-image-minimal
|
||||
core-image-sato
|
||||
meta-toolchain
|
||||
meta-toolchain-sdk
|
||||
adt-installer
|
||||
meta-ide-support
|
||||
|
||||
You can also run generated qemu images with a command like 'runqemu qemux86'
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following <filename>bitbake</filename> command starts the build:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake -k core-image-minimal
|
||||
</literallayout>
|
||||
<note>Be sure to check the settings in the <filename>local.conf</filename>
|
||||
before starting the build.</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='examining-the-default-config-smp-behavior'>
|
||||
<title>Examining the Default <filename>CONFIG_SMP</filename> Behavior</title>
|
||||
|
||||
<para>
|
||||
By default, <filename>CONFIG_SMP</filename> supports multiple processor machines.
|
||||
To see this default setting from within the QEMU emulator, boot your image using
|
||||
the emulator as follows:
|
||||
<literallayout class='monospaced'>
|
||||
$ runqemu qemux86 qemuparams="-smp 4"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Login to the machine using <filename>root</filename> with no password.
|
||||
After logging in, enter the following command to see how many processors are
|
||||
being supported in the emulator.
|
||||
The emulator reports support for the number of processors you specified using
|
||||
the <filename>-smp</filename> option, four in this case:
|
||||
<literallayout class='monospaced'>
|
||||
# cat /proc/cpuinfo | grep processor
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
#
|
||||
</literallayout>
|
||||
To check the setting for <filename>CONFIG_SMP</filename>, you can use the
|
||||
following command:
|
||||
<literallayout class='monospaced'>
|
||||
zcat /proc/config.gz | grep CONFIG_SMP
|
||||
</literallayout>
|
||||
The console returns the following showing that multi-processor machine support
|
||||
is set:
|
||||
<literallayout class='monospaced'>
|
||||
CONFIG_SMP=y
|
||||
</literallayout>
|
||||
Logout of the emulator using the <filename>exit</filename> command and
|
||||
then close it down.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='changing-the-config-smp-configuration-using-menuconfig'>
|
||||
<title>Changing the <filename>CONFIG_SMP</filename> Configuration Using <filename>menuconfig</filename></title>
|
||||
|
||||
<para>
|
||||
The <filename>menuconfig</filename> tool provides an interactive method with which
|
||||
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.
|
||||
If you have not sourced this script do so with the following commands:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ source oe-init-build-env
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
After setting up the environment to run <filename>menuconfig</filename>, you are ready
|
||||
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
|
||||
<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
|
||||
<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 menuconfig
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once <filename>menuconfig</filename> launches, navigate through the user interface
|
||||
to find the <filename>CONFIG_SMP</filename> configuration setting.
|
||||
You can find it at <filename>Processor Type and Features</filename>.
|
||||
The configuration selection is
|
||||
<filename>Symmetric Multi-processing Support</filename>.
|
||||
After using the arrow keys to highlight this selection, press "n" to turn it off.
|
||||
Then, exit out and save your selections.
|
||||
</para>
|
||||
|
||||
<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
|
||||
when it is built.
|
||||
You can find and examine this file 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...
|
||||
...656ed30-r1/linux-qemux86-standard-build
|
||||
</literallayout>
|
||||
<note>
|
||||
The previous example directory is artificially split and many of the characters
|
||||
in the actual filename are omitted in order to make it more readable.
|
||||
Also, depending on the kernel you are using, the exact pathname might differ
|
||||
slightly.
|
||||
</note>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Within the <filename>.config</filename> file, you can see the following setting:
|
||||
<literallayout class='monospaced'>
|
||||
# CONFIG_SMP is not set
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A good method to isolate changed configurations is to use a combination of the
|
||||
<filename>menuconfig</filename> tool and simple shell commands.
|
||||
Before changing configurations with <filename>menuconfig</filename>, copy the
|
||||
existing <filename>.config</filename> and rename it to something else,
|
||||
use <filename>menuconfig</filename> to make
|
||||
as many changes an you want and save them, then compare the renamed configuration
|
||||
file against the newly created file.
|
||||
You can use the resulting differences as your base to create configuration fragments
|
||||
to permanently save in your kernel layer.
|
||||
<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>
|
||||
from which to work.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='recompiling-the-kernel-and-testing-the-new-configuration'>
|
||||
<title>Recompiling the Kernel and Testing the New Configuration</title>
|
||||
|
||||
<para>
|
||||
At this point, you are ready to recompile your kernel image with
|
||||
the new setting in effect using the BitBake command below:
|
||||
<literallayout class='monospaced'>
|
||||
$ bitbake linux-yocto
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Now run the QEMU emulator and pass it the same multi-processor option as before:
|
||||
<literallayout class='monospaced'>
|
||||
$ runqemu qemux86 qemuparams="-smp 4"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Login to the machine using <filename>root</filename> with no password
|
||||
and test for the number of processors the kernel supports:
|
||||
<literallayout class='monospaced'>
|
||||
# cat /proc/cpuinfo | grep processor
|
||||
processor : 0
|
||||
#
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
From the output, you can see that the kernel no longer supports multi-processor systems.
|
||||
The output indicates support for a single processor. You can verify the
|
||||
<filename>CONFIG_SMP</filename> setting by using this command:
|
||||
<literallayout class='monospaced'>
|
||||
zcat /proc/config.gz | grep CONFIG_SMP
|
||||
</literallayout>
|
||||
The console returns the following output:
|
||||
<literallayout class='monospaced'>
|
||||
# CONFIG_SMP is not set
|
||||
</literallayout>
|
||||
You have successfully reconfigured the kernel.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id='adding-kernel-recipes'>
|
||||
<title>Adding Kernel Recipes</title>
|
||||
|
||||
<para>
|
||||
A future release of this manual will present an example that adds kernel recipes, which provide
|
||||
new functionality to the kernel.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<imagedata fileref="figures/wip.png"
|
||||
width="2in" depth="3in" align="center" scalefit="1" />
|
||||
</para>
|
||||
</section>
|
||||
</appendix>
|
||||
|
||||
<!--
|
||||
@@ -75,12 +75,12 @@
|
||||
Experience shows that buildbot is a good fit for this role.
|
||||
What works well is to configure buildbot to make two types of builds:
|
||||
incremental and full (from scratch).
|
||||
See <ulink url='http://autobuilder.yoctoproject.org:8010/'>Welcome to the buildbot for the
|
||||
See <ulink url='http://autobuilder.yoctoproject.org:8010/'>the buildbot for the
|
||||
Yocto Project</ulink> for an example implementation that uses buildbot.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You can tie an incremental build to a commit hook that triggers the build
|
||||
You can tie incremental builds to a commit hook that triggers the build
|
||||
each time a commit is made to the metadata.
|
||||
This practice results in useful acid tests that determine whether a given commit
|
||||
breaks the build in some serious way.
|
||||
@@ -130,7 +130,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 source directory (poky) 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,7 +148,7 @@
|
||||
<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
|
||||
Unpacking the tarball gives you a hierarchical source directory that lets you develop
|
||||
using the Yocto Project.
|
||||
</para>
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
<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, installers for 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>
|
||||
@@ -207,44 +207,43 @@
|
||||
<filename>formfactor_0.0.bb</filename> and <filename>formfactor_0.0.bbappend</filename>).
|
||||
</para>
|
||||
<para>Information in append files overrides the information in the similarly-named recipe file.
|
||||
For an example of an append file in use, see the
|
||||
"<link linkend='using-bbappend-files'>Using .bbappend Files</link>" section.
|
||||
</para></listitem>
|
||||
<listitem><para id='bitbake-term'><emphasis>BitBake:</emphasis>
|
||||
The task executor and scheduler used by
|
||||
For examples of <filename>.bbappend</filename> file in use, see the
|
||||
"<link linkend='using-bbappend-files'>Using .bbappend Files</link>" and
|
||||
"<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 BitBake documentation
|
||||
in the <filename>bitbake/doc/manual</filename> directory of the
|
||||
<link linkend='source-directory'>Source Directory</link>.</para></listitem>
|
||||
For more information on BitBake, see the <ulink url='http://bitbake.berlios.de/manual/'>
|
||||
BitBake documentation</ulink>.</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
|
||||
(i.e. <filename>&OE_INIT_FILE;</filename>).
|
||||
environment script that is found in the source directory
|
||||
(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>
|
||||
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 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
|
||||
<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'>
|
||||
$ source &OE_INIT_PATH;
|
||||
$ source oe-init-build-env
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Provide a directory path and specifically name the build
|
||||
directory.
|
||||
This next example creates a Build Directory named <filename>YP-&POKYVERSION;</filename>
|
||||
This next example creates a build directory named <filename>YP-&POKYVERSION;</filename>
|
||||
in your home directory within the directory <filename>mybuilds</filename>.
|
||||
If <filename>mybuilds</filename> does not exist, the directory is created for you:
|
||||
<literallayout class='monospaced'>
|
||||
$ source &OE_INIT_PATH; $HOME/mybuilds/YP-&POKYVERSION;
|
||||
</literallayout></para></listitem>
|
||||
<listitem><para>Provide an existing directory to use as the Build Directory.
|
||||
<listitem><para>Provide an existing directory to use as the build directory.
|
||||
This example uses the existing <filename>mybuilds</filename> directory
|
||||
as the Build Directory.
|
||||
as the build directory.
|
||||
<literallayout class='monospaced'>
|
||||
$ source &OE_INIT_PATH; $HOME/mybuilds/
|
||||
</literallayout></para></listitem>
|
||||
@@ -254,7 +253,7 @@
|
||||
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.
|
||||
<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
|
||||
@@ -264,14 +263,14 @@
|
||||
<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>
|
||||
<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
|
||||
<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).
|
||||
@@ -282,19 +281,19 @@
|
||||
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 a cross-development toolchain
|
||||
installer that when run installs the toolchain that contains the development tools you
|
||||
need to cross-compile and test your software.
|
||||
The Yocto Project ships with images that contain installers for
|
||||
toolchains for supported architectures as well.
|
||||
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 or QEMU
|
||||
and for specific use cases.
|
||||
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>
|
||||
"<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
|
||||
@@ -303,36 +302,22 @@
|
||||
<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 id='oe-core'><emphasis>OE-Core:</emphasis> A core set of metadata originating
|
||||
<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> In the context of the Yocto Project,
|
||||
this term refers to the packaged output from a baked recipe.
|
||||
<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>
|
||||
<para>It is worth noting that the term "package" can, in general, have subtle
|
||||
meanings. For example, the packages refered to in the
|
||||
"<ulink url='&YOCTO_DOCS_QS_URL;#packages'>The Packages</ulink>" section are
|
||||
compiled binaries that when installed add functionality to your Linux
|
||||
distribution.</para>
|
||||
<para>Another point worth noting is that historically within the Yocto Project,
|
||||
recipes were referred to as packages - thus, the existence of several BitBake
|
||||
variables that are seemingly mis-named,
|
||||
(e.g. <ulink url='&YOCTO_DOCS_REF_URL;#var-PR'><filename>PR</filename></ulink>,
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-PRINC'><filename>PRINC</filename></ulink>,
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-PV'><filename>PV</filename></ulink>, and
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-PE'><filename>PE</filename></ulink>).
|
||||
</para></listitem>
|
||||
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 sense, it is an open-source project that was initially developed
|
||||
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
|
||||
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.
|
||||
@@ -344,20 +329,19 @@
|
||||
<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
|
||||
the <filename>poky</filename> Git repository
|
||||
<filename>git://git.yoctoproject.org/poky</filename>.
|
||||
<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
|
||||
<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
|
||||
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
|
||||
<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
|
||||
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.
|
||||
@@ -366,22 +350,22 @@
|
||||
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
|
||||
<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.
|
||||
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
|
||||
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 by using Git tags that are part of the repository.</para>
|
||||
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
|
||||
@@ -432,13 +416,13 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When you build an image using the Yocto Project, the build process uses a
|
||||
known list of licenses to ensure compliance.
|
||||
When you build an image using Yocto Project, the build process uses a known list of licenses to
|
||||
ensure compliance.
|
||||
You can find this list in the Yocto Project files directory at
|
||||
<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='build-directory'>build directory</link> at
|
||||
<filename>tmp/deploy/images/licenses</filename>.
|
||||
</para>
|
||||
|
||||
@@ -466,12 +450,6 @@
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit/cgit.cgi/poky/tree/meta/files/common-licenses'>here</ulink>.
|
||||
This wiki page discusses the license infrastructure used by the Yocto Project.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For information that can help you to maintain compliance with various open source licensing
|
||||
during the lifecycle of a product created using the Yocto Project, see the
|
||||
"<link linkend='maintaining-open-source-license-compliance-during-your-products-lifecycle'>Maintaining Open Source License Compliance During Your Product's Lifecycle</link>" section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id='git'>
|
||||
@@ -535,9 +513,10 @@
|
||||
It is important to understand that Git tracks content change and not files.
|
||||
Git uses "branches" to organize different development efforts.
|
||||
For example, the <filename>poky</filename> repository has
|
||||
<filename>bernard</filename>,
|
||||
<filename>edison</filename>, <filename>denzil</filename>, <filename>danny</filename>
|
||||
and <filename>master</filename> branches among others.
|
||||
<filename>laverne</filename>, <filename>bernard</filename>,
|
||||
<filename>edison</filename>, <filename>denzil</filename> and
|
||||
<filename>master</filename> branches among
|
||||
others.
|
||||
You can see all the branches by going to
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi/poky/'></ulink> and
|
||||
clicking on the
|
||||
@@ -582,8 +561,9 @@
|
||||
at the time you created your local branch, which could be
|
||||
different than the files at the time of a similarly named release.
|
||||
In other words, creating and checking out a local branch based on the
|
||||
<filename>&DISTRO_NAME;</filename> branch name is not the same as
|
||||
cloning and checking out the <filename>master</filename> branch.
|
||||
<filename>&DISTRO_NAME;</filename> branch name is not the same as creating and
|
||||
checking out a local branch based on the <filename>&DISTRO_NAME;-&DISTRO;</filename>
|
||||
release.
|
||||
Keep reading to see how you create a local snapshot of a Yocto Project Release.
|
||||
</para>
|
||||
|
||||
@@ -599,7 +579,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Some key tags are <filename>bernard-5.0</filename>, <filename>denzil-7.0</filename>,
|
||||
Some key tags are <filename>laverne-4.0</filename>, <filename>bernard-5.0</filename>,
|
||||
and <filename>&DISTRO_NAME;-&POKYVERSION;</filename>.
|
||||
These tags represent Yocto Project releases.
|
||||
</para>
|
||||
@@ -681,18 +661,17 @@
|
||||
a working branch on your local machine where you can isolate work.
|
||||
It is a good idea to use local branches when adding specific features or changes.
|
||||
This way if you don’t like what you have done you can easily get rid of the work.</para></listitem>
|
||||
<listitem><para><emphasis><filename>git branch</filename>:</emphasis> Reports
|
||||
existing local branches and
|
||||
tells you the branch in which you are currently working.</para></listitem>
|
||||
<listitem><para><emphasis><filename>git branch</filename>:</emphasis> Reports existing branches and
|
||||
tells you which branch in which you are currently working.</para></listitem>
|
||||
<listitem><para><emphasis><filename>git branch -D <branch-name></filename>:</emphasis>
|
||||
Deletes an existing local branch.
|
||||
You need to be in a local branch other than the one you are deleting
|
||||
in order to delete <filename><branch-name></filename>.</para></listitem>
|
||||
Deletes an existing branch.
|
||||
You need to be in a branch other than the one you are deleting
|
||||
in order to delete <branch-name>.</para></listitem>
|
||||
<listitem><para><emphasis><filename>git pull</filename>:</emphasis> Retrieves information
|
||||
from an upstream Git
|
||||
repository and places it in your local Git repository.
|
||||
You use this command to make sure you are synchronized with the repository
|
||||
from which you are basing changes (.e.g. the master branch).</para></listitem>
|
||||
from which you are basing changes (.e.g. the master repository).</para></listitem>
|
||||
<listitem><para><emphasis><filename>git push</filename>:</emphasis> Sends all your local changes you
|
||||
have committed to an upstream Git repository (e.g. a contribution repository).
|
||||
The maintainer of the project draws from these repositories when adding your changes to the
|
||||
@@ -774,8 +753,6 @@
|
||||
A somewhat formal method exists by which developers commit changes and push them into the
|
||||
"contrib" area and subsequently request that the maintainer include them into "master"
|
||||
This process is called “submitting a patch” or “submitting a change.”
|
||||
For information on submitting patches and changes, see the
|
||||
"<link linkend='how-to-submit-a-change'>How to Submit a Change</link>" section.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -838,18 +815,13 @@
|
||||
<filename>send-pull-request</filename> that ship with the release to facilitate this
|
||||
workflow.
|
||||
You can find these scripts in the local Yocto Project files Git repository in
|
||||
the <filename>scripts</filename> directory.</para>
|
||||
<para>You can find more information on these scripts in the
|
||||
"<link linkend='pushing-a-change-upstream'>Using
|
||||
Scripts to Push a Change Upstream and Request a Pull</link>" section.
|
||||
</para></listitem>
|
||||
the <filename>scripts</filename> directory.</para></listitem>
|
||||
<listitem><para><emphasis>Patch Workflow:</emphasis> This workflow allows you to notify the
|
||||
maintainer through an email that you have a change (or patch) you would like considered
|
||||
for the "master" branch of the Git repository.
|
||||
To send this type of change you format the patch and then send the email using the Git commands
|
||||
<filename>git format-patch</filename> and <filename>git send-email</filename>.
|
||||
You can find information on how to submit changes
|
||||
later in this chapter.</para></listitem>
|
||||
You can find information on how to submit later in this chapter.</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
@@ -881,9 +853,8 @@
|
||||
a bug.</para></listitem>
|
||||
<listitem><para>When submitting a new bug, be sure to choose the appropriate
|
||||
Classification, Product, and Component for which the issue was found.
|
||||
Defects for Yocto Project fall into one of six classifications: Yocto Project
|
||||
Components, Infrastructure, Build System & Metadata, Documentation,
|
||||
QA/Testing, and Runtime.
|
||||
Defects for Yocto Project fall into one of four classifications: Yocto Projects,
|
||||
Infrastructure, Poky, and Yocto Metadata Layers.
|
||||
Each of these Classifications break down into multiple Products and, in some
|
||||
cases, multiple Components.</para></listitem>
|
||||
<listitem><para>Use the bug form to choose the correct Hardware and Architecture
|
||||
@@ -916,7 +887,7 @@
|
||||
can be reviewed and merged by the appropriate maintainer.
|
||||
For a list of the Yocto Project and related mailing lists, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#resources-mailinglist'>Mailing lists</ulink>" section in
|
||||
the Yocto Project Reference Manual.
|
||||
The Yocto Project Reference Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -932,8 +903,7 @@
|
||||
<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
|
||||
<filename>yoctoproject.org</filename> (unless the
|
||||
<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>
|
||||
@@ -997,8 +967,7 @@
|
||||
should almost always provide a more detailed description of what you did (i.e.
|
||||
the body of the commit message).
|
||||
The only exceptions for not providing a detailed description would be if your
|
||||
change is a simple, self-explanatory change that needs no further description
|
||||
beyond the summary.
|
||||
change is a simple, self-explanatory change that needs no description.
|
||||
Here are the guidelines for composing a commit message:
|
||||
<itemizedlist>
|
||||
<listitem><para>Provide a single-line, short summary of the change.
|
||||
@@ -1018,11 +987,11 @@
|
||||
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 beginning) as follows:
|
||||
bug ID in the description (typically at the end) as follows:
|
||||
<literallayout class='monospaced'>
|
||||
[YOCTO #<bug-id>]
|
||||
|
||||
<detailed description of change>
|
||||
|
||||
[YOCTO #<bug-id>]
|
||||
</literallayout></para></listitem>
|
||||
Where <bug-id> is replaced with the specific bug ID from the
|
||||
Yocto Project Bugzilla instance.
|
||||
@@ -1036,12 +1005,11 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Following are general instructions for both pushing changes upstream and for submitting
|
||||
changes as patches.
|
||||
Following are general instructions for both pushing changes upstream and for submitting changes as patches.
|
||||
</para>
|
||||
|
||||
<section id='pushing-a-change-upstream'>
|
||||
<title>Using Scripts to Push a Change Upstream and Request a Pull</title>
|
||||
<title>Pushing a Change Upstream and Requesting a Pull</title>
|
||||
|
||||
<para>
|
||||
The basic flow for pushing a change to an upstream "contrib" Git repository is as follows:
|
||||
@@ -1059,13 +1027,8 @@
|
||||
pull requests to the Yocto Project.
|
||||
These scripts are <filename>create-pull-request</filename> and
|
||||
<filename>send-pull-request</filename>.
|
||||
You can find these scripts in the <filename>scripts</filename> directory
|
||||
within the <link linkend='source-directory'>Source Directory</link>.</para>
|
||||
<para>Using these scripts correctly formats the requests without introducing any
|
||||
whitespace or HTML formatting.
|
||||
The maintainer that receives your patches needs to be able to save and apply them
|
||||
directly from your emails.
|
||||
Using these scripts is the preferred method for sending patches.</para>
|
||||
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:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -1082,15 +1045,11 @@
|
||||
</section>
|
||||
|
||||
<section id='submitting-a-patch'>
|
||||
<title>Using Email to Submit a Patch</title>
|
||||
|
||||
<para>
|
||||
You can submit patches without using the <filename>create-pull-request</filename> and
|
||||
<filename>send-pull-request</filename> scripts described in the previous section.
|
||||
Keep in mind, the preferred method is to use the scripts, however.
|
||||
</para>
|
||||
<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
|
||||
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
|
||||
@@ -1102,8 +1061,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here is the general procedure on how to submit a patch through email without using the
|
||||
scripts:
|
||||
Here is the general procedure on how to submit a patch through email:
|
||||
<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>
|
||||
@@ -1141,9 +1099,16 @@
|
||||
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 are or will be a frequent contributor to the Yocto Project
|
||||
or to OpenEmbedded, you might consider requesting a contrib area and the
|
||||
necessary associated rights.</note></listitem>
|
||||
<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>
|
||||
<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
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
<para>
|
||||
This chapter introduces the Yocto Project and gives you an idea of what you need to get started.
|
||||
You can find enough information to set up your development host and build or use images for
|
||||
hardware supported by the Yocto Project by reading the
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;'>Yocto Project Quick Start</ulink>.
|
||||
hardware supported by the Yocto Project by reading
|
||||
<ulink url='&YOCTO_DOCS_QS_URL;'>
|
||||
The Yocto Project Quick Start</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
<para>
|
||||
You can use the OpenEmbedded build system, which uses
|
||||
BitBake to develop complete Linux
|
||||
<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,12 +55,7 @@
|
||||
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
|
||||
and officially supported.
|
||||
For a list of the distributions under validation and their status, see the
|
||||
"<ulink url='&YOCTO_DOCS_REF_URL;#detailed-supported-distros'>Supported Linux Distributions</ulink>" section
|
||||
in the Yocto Project Reference Manual and the wiki page at
|
||||
<ulink url='&YOCTO_WIKI_URL;/wiki/Distribution_Support'>Distribution Support</ulink>.</para>
|
||||
<para>
|
||||
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
|
||||
@@ -70,12 +66,12 @@
|
||||
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>
|
||||
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.
|
||||
<note>
|
||||
Regardless of the method you use, this manual refers to the resulting local
|
||||
hierarchical set of files as the "Source Directory."
|
||||
hierarchical set of files as the "source directory."
|
||||
</note>
|
||||
<itemizedlist>
|
||||
<listitem><para><emphasis>Tarball Extraction:</emphasis> If you are not going to contribute
|
||||
@@ -84,7 +80,7 @@
|
||||
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
|
||||
into the current working directory and sets up the local source directory
|
||||
with a top-level folder named <filename>&YOCTO_POKY;</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ tar xfj &YOCTO_POKY_TARBALL;
|
||||
@@ -124,26 +120,26 @@
|
||||
If you are going to be making modifications to a supported Yocto Project kernel, you
|
||||
need to establish local copies of the source.
|
||||
You can find Git repositories of supported Yocto Project Kernels organized under
|
||||
"Yocto Linux Kernel" in the Yocto Project Source Repositories at
|
||||
"Yocto Project Linux Kernel" in the Yocto Project Source Repositories at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'></ulink>.</para>
|
||||
<para>This setup can involve creating a bare clone of the Yocto Project kernel and then
|
||||
<para>This setup involves creating a bare clone of the Yocto Project 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>
|
||||
source directory (usually <filename>poky</filename>).</para>
|
||||
<para>As an example, the following transcript shows how to create the bare clone
|
||||
of the <filename>linux-yocto-3.4</filename> kernel and then create a copy of
|
||||
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
|
||||
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>
|
||||
<para>In the following example, the bare clone is named
|
||||
<filename>linux-yocto-3.4.git</filename>, while the
|
||||
copy is named <filename>my-linux-yocto-3.4-work</filename>:
|
||||
<filename>linux-yocto-3.2.git</filename>, while the
|
||||
copy is named <filename>my-linux-yocto-3.2-work</filename>:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone --bare git://git.yoctoproject.org/linux-yocto-3.4 linux-yocto-3.4.git
|
||||
Initialized empty Git repository in /home/scottrif/linux-yocto-3.4.git/
|
||||
$ git clone --bare git://git.yoctoproject.org/linux-yocto-3.2 linux-yocto-3.2.git
|
||||
Initialized empty Git repository in /home/scottrif/linux-yocto-3.2.git/
|
||||
remote: Counting objects: 2468027, done.
|
||||
remote: Compressing objects: 100% (392255/392255), done.
|
||||
remote: Total 2468027 (delta 2071693), reused 2448773 (delta 2052498)
|
||||
@@ -152,9 +148,9 @@
|
||||
</literallayout></para>
|
||||
<para>Now create a clone of the bare clone just created:
|
||||
<literallayout class='monospaced'>
|
||||
$ git clone linux-yocto-3.4.git my-linux-yocto-3.4-work
|
||||
Cloning into 'my-linux-yocto-3.4-work'...
|
||||
done.
|
||||
$ git clone linux-yocto-3.2.git my-linux-yocto-3.2-work
|
||||
Initialized empty Git repository in /home/scottrif/my-linux-yocto-3.2-work/.git/
|
||||
Checking out files: 100% (37619/37619), done.
|
||||
</literallayout></para></listitem>
|
||||
<listitem id='poky-extras-repo'><para><emphasis>
|
||||
The <filename>poky-extras</filename> Git Repository</emphasis>:
|
||||
@@ -169,12 +165,11 @@
|
||||
<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 source directory.</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>
|
||||
repository inside the source directory, which is named <filename>poky</filename>
|
||||
in this case:
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ git clone git://git.yoctoproject.org/poky-extras poky-extras
|
||||
Initialized empty Git repository in /home/scottrif/poky/poky-extras/.git/
|
||||
remote: Counting objects: 618, done.
|
||||
@@ -193,13 +188,13 @@
|
||||
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 that you used to set up the source directory.
|
||||
Regardless of the method you use, the Yocto Project uses the following BSP layer
|
||||
naming scheme:
|
||||
<literallayout class='monospaced'>
|
||||
meta-<BSP_name>
|
||||
</literallayout>
|
||||
where <filename><BSP_name></filename> is the recognized BSP name.
|
||||
where <BSP_name> is the recognized BSP name.
|
||||
Here are some examples:
|
||||
<literallayout class='monospaced'>
|
||||
meta-crownbay
|
||||
@@ -219,18 +214,17 @@
|
||||
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 local Git repository for your source directory, 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 source directory.
|
||||
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.
|
||||
<literallayout class='monospaced'>
|
||||
$ cd ~/poky
|
||||
$ git clone git://git.yoctoproject.org/meta-intel.git
|
||||
Initialized empty Git repository in /home/scottrif/poky/meta-intel/.git/
|
||||
remote: Counting objects: 3380, done.
|
||||
@@ -248,8 +242,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>
|
||||
@@ -267,13 +262,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 set up the source directory 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,
|
||||
which is found in the
|
||||
<link linkend='build-directory'>Build Directory</link>,
|
||||
<link linkend='build-directory'>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
|
||||
@@ -284,9 +279,8 @@
|
||||
a centralized tarball download directory through the
|
||||
<filename><ulink url='&YOCTO_DOCS_REF_URL;#var-DL_DIR'>DL_DIR</ulink></filename> variable.</para></listitem>
|
||||
<listitem><para>Build the image using the <filename>bitbake</filename> command.
|
||||
If you want information on BitBake, see the user manual inculded in the
|
||||
<filename>bitbake/doc/manual</filename> directory of the
|
||||
<link linkend='source-directory'>Source Directory</link>.</para></listitem>
|
||||
If you want information on BitBake, see the user manual at
|
||||
<ulink url='&OE_DOCS_URL;/bitbake/html'></ulink>.</para></listitem>
|
||||
<listitem><para>Run the image either on the actual hardware or using the QEMU
|
||||
emulator.</para></listitem>
|
||||
</orderedlist>
|
||||
@@ -299,9 +293,8 @@
|
||||
<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
|
||||
See the <ulink url='&YOCTO_DOCS_REF_URL;#ref-images'>Reference: Images</ulink>
|
||||
section for descriptions of the types of binaries that ship with a Yocto Project
|
||||
release.
|
||||
</para>
|
||||
|
||||
@@ -320,9 +313,9 @@
|
||||
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 filesystems from
|
||||
You can get architecture-specific binaries and filesystem from
|
||||
<ulink url='&YOCTO_MACHINES_DL_URL;'>machines</ulink>.
|
||||
You can get installation scripts for stand-alone toolchains from
|
||||
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.
|
||||
@@ -367,21 +360,14 @@
|
||||
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>SSH servers exist in some QEMU images.
|
||||
The <filename>core-image-sato</filename> QEMU image has a Dropbear secure
|
||||
shell (ssh) server that runs with the root password disabled.
|
||||
The <filename>core-image-basic</filename> and <filename>core-image-lsb</filename> QEMU images
|
||||
have OpenSSH instead of Dropbear.
|
||||
Including these SSH servers allow you to use standard <filename>ssh</filename> and
|
||||
<filename>scp</filename> commands.
|
||||
The <filename>core-image-minimal</filename> QEMU image, however, contains no ssh
|
||||
server.</para></listitem>
|
||||
<listitem><para>You can use a provided, user-space NFS server to boot the QEMU session
|
||||
using a local copy of the root filesystem on the host.
|
||||
In order to make this connection, you must extract a root filesystem tarball by using the
|
||||
<filename>runqemu-extract-sdk</filename> command.
|
||||
After running the command, you must then point the <filename>runqemu</filename>
|
||||
script to the extracted directory instead of a root filesystem image file.</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>
|
||||
|
||||
@@ -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>
|
||||
@@ -41,19 +41,9 @@
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>October 2012</date>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.1</revnumber>
|
||||
<date>April 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.2</revnumber>
|
||||
<date>May 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
<copyright>
|
||||
@@ -63,16 +53,17 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
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 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
|
||||
<ulink url='&YOCTO_DOCS_DEV_URL;'>Yocto Project Development Manual</ulink> on
|
||||
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.
|
||||
For the latest version of this manual, see the manual on the website.
|
||||
</note>
|
||||
@@ -86,11 +77,15 @@
|
||||
|
||||
<xi:include href="dev-manual-newbie.xml"/>
|
||||
|
||||
<xi:include href="dev-manual-model.xml"/>
|
||||
|
||||
<xi:include href="dev-manual-common-tasks.xml"/>
|
||||
|
||||
<xi:include href="dev-manual-model.xml"/>
|
||||
|
||||
<xi:include href="dev-manual-bsp-appendix.xml"/>
|
||||
|
||||
<xi:include href="dev-manual-kernel-appendix.xml"/>
|
||||
|
||||
</book>
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
<!--
|
||||
vim: expandtab tw=80 ts=4
|
||||
-->
|
||||
|
||||
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 60 KiB |
BIN
documentation/dev-manual/figures/kernel-example-repos-denzil.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 36 KiB |
BIN
documentation/dev-manual/figures/kernel-overview-2.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
documentation/dev-manual/figures/kernel-overview-3-denzil.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
documentation/dev-manual/figures/wip.png
Normal file
|
After Width: | Height: | Size: 34 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;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -24,7 +24,7 @@
|
||||
<para>
|
||||
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, both flexibility and maintainability are key concerns.
|
||||
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.
|
||||
For example, prior methods such as applying hundreds of patches to an extracted
|
||||
@@ -45,7 +45,7 @@
|
||||
management techniques.</para></listitem>
|
||||
<listitem><para>Deliver the most up-to-date kernel possible while still ensuring that
|
||||
the baseline kernel is the most stable official release.</para></listitem>
|
||||
<listitem><para>Include major technological features as part of the Yocto Project's
|
||||
<listitem><para>Include major technological features as part of Yocto Project's
|
||||
upward revision strategy.</para></listitem>
|
||||
<listitem><para>Present a kernel Git repository that, similar to the upstream
|
||||
<filename>kernel.org</filename> tree,
|
||||
@@ -86,7 +86,7 @@
|
||||
The ultimate source for kernels available through the Yocto Project are released kernels
|
||||
from <filename>kernel.org</filename>.
|
||||
In addition to a foundational kernel from <filename>kernel.org</filename>, the
|
||||
kernels available contain a mix of important new mainline
|
||||
kernels available through the contain a mix of important new mainline
|
||||
developments, non-mainline developments (when there is no alternative),
|
||||
Board Support Package (BSP) developments,
|
||||
and custom features.
|
||||
@@ -255,7 +255,7 @@
|
||||
In other words, the divisions of the kernel are transparent and are not relevant
|
||||
to the developer on a day-to-day basis.
|
||||
From the developer's perspective, this path is the "master" branch.
|
||||
The developer does not need to be aware of the existence of any other branches at all.
|
||||
The developer does not need not be aware of the existence of any other branches at all.
|
||||
Of course, there is value in the existence of these branches
|
||||
in the tree, should a person decide to explore them.
|
||||
For example, a comparison between two BSPs at either the commit level or at the line-by-line
|
||||
@@ -293,7 +293,7 @@
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#git'>Git</ulink>"
|
||||
section in the Yocto Project Development Manual.
|
||||
These referenced sections overview Git and describe a minimal set of
|
||||
commands that allows you to be functional using Git.
|
||||
commands that allow you to be functional using Git.
|
||||
<note>
|
||||
You can use as much, or as little, of what Git has to offer to accomplish what
|
||||
you need for your project.
|
||||
@@ -320,7 +320,7 @@
|
||||
Conceptually, configuration of a Yocto Project kernel occurs similarly to that needed for any
|
||||
Linux kernel.
|
||||
The build process for a Yocto Project kernel uses a <filename>.config</filename> file, which
|
||||
is created through the Linux Kernel Configuration (LKC) tool.
|
||||
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>
|
||||
tool as built by BitBake.
|
||||
@@ -344,8 +344,8 @@
|
||||
After the tool is built, you can interact with it normally.
|
||||
You can see how <filename>menuconfig</filename> is used to change a simple
|
||||
kernel configuration in the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#configuring-the-kernel'>Configuring the Kernel</ulink>"
|
||||
section of the Yocto Project Development Manual.
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#changing-the-config-smp-configuration-using-menuconfig'>Changing the <filename>CONFIG_SMP</filename> Configuration Using <filename>menuconfig</filename></ulink>"
|
||||
section of The Yocto Project Development Manual.
|
||||
For general information on <filename>menuconfig</filename>, see
|
||||
<ulink url='http://en.wikipedia.org/wiki/Menuconfig'></ulink>.
|
||||
</para></listitem>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<title>Yocto Project Kernel Architecture and Use Manual</title>
|
||||
|
||||
<section id='kernel-intro-section'>
|
||||
<section id='book-intro'>
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
The Yocto Project presents kernels as a fully patched, history-clean Git
|
||||
@@ -40,14 +40,14 @@
|
||||
<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>
|
||||
|
||||
<para>
|
||||
For more discussion on the Yocto Project kernel, you can see these sections
|
||||
in the Yocto Project Development Manual:
|
||||
in <ulink url='&YOCTO_DOCS_DEV_URL;'>The Yocto Project Development Manual</ulink>:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#kernel-overview'>Kernel Overview</ulink>"</para></listitem>
|
||||
@@ -55,9 +55,7 @@
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#kernel-modification-workflow'>Kernel Modification Workflow</ulink>"
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#patching-the-kernel'>Patching the Kernel</ulink>"</para></listitem>
|
||||
<listitem><para>
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#configuring-the-kernel'>Configuring the Kernel</ulink>"</para></listitem>
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#dev-manual-kernel-appendix'>Kernel Modification Example</ulink>"</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<para>
|
||||
This section describes construction of the Yocto Project kernel source repositories
|
||||
as accomplished by the Yocto Project team to create kernel repositories.
|
||||
These kernel repositories are found under the heading "Yocto Linux Kernel" at
|
||||
These kernel repositories are found at
|
||||
<ulink url='&YOCTO_GIT_URL;/cgit.cgi'>&YOCTO_GIT_URL;/cgit.cgi</ulink>
|
||||
and can be shipped as part of a Yocto Project release.
|
||||
The team creates these repositories by
|
||||
@@ -53,8 +53,8 @@
|
||||
</literallayout>
|
||||
For another example of how to set up a local Git repository of the Yocto Project
|
||||
kernel files, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#local-kernel-files'>Yocto Project 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
|
||||
@@ -114,9 +114,8 @@
|
||||
of actions, or into an existing equivalent script that is already part of the
|
||||
shipped kernel.</para></listitem>
|
||||
<listitem><para>Extra features are appended to the top-level feature description.
|
||||
These features can come from the
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-KERNEL_FEATURES'><filename>KERNEL_FEATURES</filename></ulink>
|
||||
variable in recipes.</para></listitem>
|
||||
These features can come from the <filename>KERNEL_FEATURES</filename> variable in
|
||||
recipes.</para></listitem>
|
||||
<listitem><para>Each extra feature is located, compiled and appended to the script
|
||||
as described in step three.</para></listitem>
|
||||
<listitem><para>The script is executed to produce a series of <filename>meta-*</filename>
|
||||
@@ -159,9 +158,8 @@
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>The
|
||||
<ulink url='&YOCTO_DOCS_REF_URL;#var-SRC_URI'><filename>SRC_URI</filename></ulink> points
|
||||
to the kernel Git repository.</para></listitem>
|
||||
<listitem><para>The <filename>SRC_URI</filename> points to the kernel Git
|
||||
repository.</para></listitem>
|
||||
<listitem><para>A BSP build branch exists.
|
||||
This branch has the following form:
|
||||
<literallayout class='monospaced'>
|
||||
@@ -213,7 +211,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
This behavior means that all the generated files for a particular machine or BSP are now in
|
||||
What this means, is that all the generated files for a particular machine or BSP are now in
|
||||
the build tree directory.
|
||||
The files include the final <filename>.config</filename> file, all the <filename>.o</filename>
|
||||
files, the <filename>.a</filename> files, and so forth.
|
||||
@@ -226,7 +224,7 @@
|
||||
<title>Workflow Examples</title>
|
||||
|
||||
<para>
|
||||
As previously noted, the Yocto Project kernel has built-in Git integration.
|
||||
As previously noted, the Yocto Project kernel has built in Git integration.
|
||||
However, these utilities are not the only way to work with the kernel repository.
|
||||
The Yocto Project has not made changes to Git or to other tools that
|
||||
would invalidate alternate workflows.
|
||||
@@ -242,7 +240,7 @@
|
||||
<ulink url='http://git-scm.com/documentation'></ulink>.
|
||||
You can find a simple overview of using Git with the Yocto Project in the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#git'>Git</ulink>"
|
||||
section of the Yocto Project Development Manual.
|
||||
section of The Yocto Project Development Manual.
|
||||
</para>
|
||||
|
||||
<section id='change-inspection-kernel-changes-commits'>
|
||||
@@ -370,10 +368,10 @@
|
||||
The Yocto Project provides scripts that help you work in a collaborative development
|
||||
environment.
|
||||
For information on these scripts, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#pushing-a-change-upstream'>Using Scripts to Push a Change
|
||||
Upstream and Request a Pull</ulink>" and
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#submitting-a-patch'>Using Email to Submit a Patch</ulink>"
|
||||
sections in the Yocto Project Development Manual.
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#pushing-a-change-upstream'>Pushing a Change
|
||||
Upstream and Requesting a Pull</ulink>" and
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#submitting-a-patch'>Submitting a Patch Through
|
||||
Email</ulink>" sections in The Yocto Project Development Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -421,10 +419,10 @@
|
||||
# bulk export of ALL modifications without separation or division
|
||||
# of the changes
|
||||
|
||||
$ git add .
|
||||
$ git commit -s -a -m <msg>
|
||||
> git add .
|
||||
> git commit -s -a -m >commit message<
|
||||
or
|
||||
$ git commit -s -a # and interact with $EDITOR
|
||||
> git commit -s -a # and interact with $EDITOR
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -461,15 +459,15 @@
|
||||
|
||||
<literallayout class='monospaced'>
|
||||
# edit a file
|
||||
$ vi <path>/file
|
||||
> vi >path</file
|
||||
# stage the change
|
||||
$ git add <path>/file
|
||||
> git add >path</file
|
||||
# commit the change
|
||||
$ git commit -s
|
||||
> git commit -s
|
||||
# remove a file
|
||||
$ git rm <path>/file
|
||||
> git rm >path</file
|
||||
# commit the change
|
||||
$ git commit -s
|
||||
> git commit -s
|
||||
|
||||
... etc.
|
||||
</literallayout>
|
||||
@@ -496,25 +494,25 @@
|
||||
associated with development by using the following commands:
|
||||
|
||||
<literallayout class='monospaced'>
|
||||
$ Git add <path>/file
|
||||
$ Git commit --amend
|
||||
$ Git rebase or Git rebase -i
|
||||
> Git add >path</file
|
||||
> Git commit --amend
|
||||
> Git rebase or Git rebase -i
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Again, assuming that the changes have not been pushed upstream, and that
|
||||
no pending works-in-progress exist (use <filename>git status</filename> to check), then
|
||||
no pending works-in-progress exists (use <filename>git status</filename> to check), then
|
||||
you can revert (undo) commits by using the following commands:
|
||||
|
||||
<literallayout class='monospaced'>
|
||||
# remove the commit, update working tree and remove all
|
||||
# traces of the change
|
||||
$ git reset --hard HEAD^
|
||||
> git reset --hard HEAD^
|
||||
# remove the commit, but leave the files changed and staged for re-commit
|
||||
$ git reset --soft HEAD^
|
||||
> git reset --soft HEAD^
|
||||
# remove the commit, leave file change, but not staged for commit
|
||||
$ git reset --mixed HEAD^
|
||||
> git reset --mixed HEAD^
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -542,7 +540,7 @@
|
||||
<para>
|
||||
This section describes how you can extract committed changes from a working directory
|
||||
by exporting them as patches.
|
||||
Once the changes have been extracted, you can use the patches for upstream submission,
|
||||
Once extracted, you can use the patches for upstream submission,
|
||||
place them in a Yocto Project template for automatic kernel patching,
|
||||
or apply them in many other common uses.
|
||||
</para>
|
||||
@@ -562,7 +560,7 @@
|
||||
# began. It can also be the parent branch if a branch was created
|
||||
# before development began.
|
||||
|
||||
$ git format-patch -o <dir> <first commit>..<last commit>
|
||||
> git format-patch -o <dir> <first commit>..<last commit>
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -572,14 +570,14 @@
|
||||
# Identify commits of interest.
|
||||
|
||||
# If the tree was tagged before development
|
||||
$ git format-patch -o <save dir> <tag>
|
||||
> git format-patch -o <save dir> <tag>
|
||||
|
||||
# If no tags are available
|
||||
$ git format-patch -o <save dir> HEAD^ # last commit
|
||||
$ git format-patch -o <save dir> HEAD^^ # last 2 commits
|
||||
$ git whatchanged # identify last commit
|
||||
$ git format-patch -o <save dir> <commit id>
|
||||
$ git format-patch -o <save dir> <rev-list>
|
||||
> git format-patch -o <save dir> HEAD^ # last commit
|
||||
> git format-patch -o <save dir> HEAD^^ # last 2 commits
|
||||
> git whatchanged # identify last commit
|
||||
> git format-patch -o <save dir> <commit id>
|
||||
> git format-patch -o <save dir> <rev-list>
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
@@ -590,14 +588,14 @@
|
||||
<para>
|
||||
This section describes how you can export changes from a working directory
|
||||
by pushing the changes into a master repository or by making a pull request.
|
||||
Once you have pushed the changes to the master repository, you can then
|
||||
Once you have pushed the changes in the master repository, you can then
|
||||
pull those same changes into a new kernel build at a later time.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Use this command form to push the changes:
|
||||
<literallayout class='monospaced'>
|
||||
$ git push ssh://<master_server>/<path_to_repo>
|
||||
> git push ssh://<master_server>/<path_to_repo>
|
||||
<local_branch>:<remote_branch>
|
||||
</literallayout>
|
||||
</para>
|
||||
@@ -607,13 +605,13 @@
|
||||
<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>.
|
||||
<literallayout class='monospaced'>
|
||||
$ git push ssh://git.mycompany.com/pub/git/kernel-3.4 \
|
||||
> git push ssh://git.mycompany.com/pub/git/kernel-3.4 \
|
||||
yocto/standard/common-pc/base:yocto/standard/common-pc/base
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A pull request entails using the <filename>git request-pull</filename> command to compose
|
||||
A pull request entails using <filename>git request-pull</filename> to compose
|
||||
an email to the
|
||||
maintainer requesting that a branch be pulled into the master repository, see
|
||||
<ulink url='http://github.com/guides/pull-requests'></ulink> for an example.
|
||||
@@ -652,7 +650,7 @@
|
||||
Consequently, be sure that the headers for each commit have the required information.
|
||||
For information on how to follow the Yocto Project commit message standards, see the
|
||||
"<ulink url='&YOCTO_DOCS_DEV_URL;#how-to-submit-a-change'>How to Submit a
|
||||
Change</ulink>" section in the Yocto Project Development Manual.
|
||||
Change</ulink>" section in The Yocto Project Development Manual.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -675,8 +673,8 @@
|
||||
The following is an example of dumping patches for external submission:
|
||||
<literallayout class='monospaced'>
|
||||
# dump the last 4 commits
|
||||
$ git format-patch --thread -n -o ~/rr/ HEAD^^^^
|
||||
$ git send-email --compose --subject '[RFC 0/N] <patch series summary>' \
|
||||
> git format-patch --thread -n -o ~/rr/ HEAD^^^^
|
||||
> git send-email --compose --subject '[RFC 0/N] <patch series summary>' \
|
||||
--to foo@yoctoproject.org --to bar@yoctoproject.org \
|
||||
--cc list@yoctoproject.org ~/rr
|
||||
# the editor is invoked for the 0/N patch, and when complete the entire
|
||||
@@ -743,9 +741,9 @@
|
||||
import the <filename>yocto/standard/common-pc/base</filename>
|
||||
kernel into a secondary SCM:
|
||||
<literallayout class='monospaced'>
|
||||
$ git checkout yocto/standard/common-pc/base
|
||||
$ cd .. ; echo linux/.git > .cvsignore
|
||||
$ cvs import -m "initial import" linux MY_COMPANY start
|
||||
> git checkout yocto/standard/common-pc/base
|
||||
> cd .. ; echo linux/.git > .cvsignore
|
||||
> cvs import -m "initial import" linux MY_COMPANY start
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -757,11 +755,11 @@
|
||||
The following commands illustrate how you can condense and merge two BSPs into a
|
||||
second SCM:
|
||||
<literallayout class='monospaced'>
|
||||
$ git checkout yocto/standard/common-pc/base
|
||||
$ git merge yocto/standard/common-pc-64/base
|
||||
> git checkout yocto/standard/common-pc/base
|
||||
> git merge yocto/standard/common-pc-64/base
|
||||
# resolve any conflicts and commit them
|
||||
$ cd .. ; echo linux/.git > .cvsignore
|
||||
$ cvs import -m "initial import" linux MY_COMPANY start
|
||||
> cd .. ; echo linux/.git > .cvsignore
|
||||
> cvs import -m "initial import" linux MY_COMPANY start
|
||||
</literallayout>
|
||||
</para>
|
||||
</section>
|
||||
@@ -785,9 +783,9 @@
|
||||
This section overviews the process of creating a BSP based on an
|
||||
existing similar BSP.
|
||||
The information is introductory in nature and does not provide step-by-step examples.
|
||||
For detailed information on how to create a new BSP, see
|
||||
the "<ulink url='&YOCTO_DOCS_BSP_URL;#creating-a-new-bsp-layer-using-the-yocto-bsp-script'>Creating a New BSP Layer Using the yocto-bsp Script</ulink>" section in the
|
||||
Yocto Project Board Support Package (BSP) Developer's Guide, or see the
|
||||
For detailed information on how to create a BSP given an existing similar BSP, see
|
||||
the "<ulink url='&YOCTO_DOCS_DEV_URL;#dev-manual-bsp-appendix'>BSP Development
|
||||
Example</ulink>" appendix in the Yocto Project Development Manual, or see the
|
||||
<ulink url='&YOCTO_WIKI_URL;/wiki/Transcript:_creating_one_generic_Atom_BSP_from_another'>Transcript:_creating_one_generic_Atom_BSP_from_another</ulink>
|
||||
wiki page.
|
||||
</para>
|
||||
@@ -795,10 +793,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
|
||||
<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>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
|
||||
@@ -846,7 +843,7 @@
|
||||
string, this simply means that modifications in the source
|
||||
directory have not been committed.
|
||||
<literallayout class='monospaced'>
|
||||
$ git status
|
||||
> git status
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
@@ -860,8 +857,8 @@
|
||||
<para>
|
||||
To brute force pickup and commit all such pending changes, enter the following:
|
||||
<literallayout class='monospaced'>
|
||||
$ git add .
|
||||
$ git commit -s -a -m "getting rid of -dirty"
|
||||
> git add .
|
||||
> git commit -s -a -m "getting rid of -dirty"
|
||||
</literallayout>
|
||||
</para>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -56,19 +56,9 @@
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3</revnumber>
|
||||
<date>October 2012</date>
|
||||
<date>Sometime in 2012</date>
|
||||
<revremark>Released with the Yocto Project 1.3 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.1</revnumber>
|
||||
<date>April 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.1 Release.</revremark>
|
||||
</revision>
|
||||
<revision>
|
||||
<revnumber>1.3.2</revnumber>
|
||||
<date>May 2013</date>
|
||||
<revremark>Released with the Yocto Project 1.3.2 Release.</revremark>
|
||||
</revision>
|
||||
</revhistory>
|
||||
|
||||
<copyright>
|
||||
@@ -78,13 +68,14 @@
|
||||
|
||||
<legalnotice>
|
||||
<para>
|
||||
Permission is granted to copy, distribute and/or modify this document under
|
||||
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
|
||||
<ulink url='&YOCTO_DOCS_KERNEL_URL;'>Yocto Project Kernel Architecture and Use Manual</ulink> on
|
||||
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.
|
||||
For the latest version of this manual, see the manual on the website.
|
||||
</note>
|
||||
@@ -104,6 +95,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;
|
||||
}
|
||||
|
||||