Compare commits

..

1 Commits

Author SHA1 Message Date
Richard Purdie
a053b09200 Tag inky-1.0
git-svn-id: https://svn.o-hand.com/repos/poky/tags/inky-1.0@260 311d38ba-8fff-0310-9ca6-ca027cbcb966
2006-02-10 09:51:37 +00:00
1519 changed files with 281419 additions and 153 deletions

39
.gitignore vendored
View File

@@ -1,39 +0,0 @@
*.pyc
*.pyo
/*.patch
/.repo/
/build*/
pyshtables.py
pstage/
scripts/oe-git-proxy-socks
sources/
meta-*/
buildtools/
!meta-skeleton
!meta-selftest
hob-image-*.bb
*.swp
*.orig
*.rej
*~
!meta-poky
!meta-yocto
!meta-yocto-bsp
!meta-yocto-imported
/documentation/*/eclipse/
/documentation/*/*.html
/documentation/*/*.pdf
/documentation/*/*.tgz
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.html
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.pdf
/bitbake/doc/bitbake-user-manual/bitbake-user-manual.tgz
pull-*/
bitbake/lib/toaster/contrib/tts/backlog.txt
bitbake/lib/toaster/contrib/tts/log/*
bitbake/lib/toaster/contrib/tts/.cache/*
bitbake/lib/bb/tests/runqueue-tests/bitbake-cookerdaemon.log
_toaster_clones/
downloads/
sstate-cache/
toaster.sqlite
.vscode/

114
README
View File

@@ -1,114 +0,0 @@
The poky repository master branch is no longer being updated.
You can either:
a) switch to individual clones of bitbake, openembedded-core, meta-yocto and yocto-docs
https://docs.yoctoproject.org/dev/dev-manual/poky-manual-setup.html
b) use the new bitbake-setup
https://docs.yoctoproject.org/bitbake/dev/bitbake-user-manual/bitbake-user-manual-environment-setup.html
You can find more information in our documentation: https://docs.yoctoproject.org/
Note that "poky" the distro setting is still available in meta-yocto as
before and we continue to use and maintain that.
Long live Poky!
Some further information on the background of this change follows. The
details are taken from:
https://lists.openembedded.org/g/openembedded-architecture/message/2179
TLDR: People have complained about the combo-layer built poky
repository for years. It was meant to be a temporary thing, we now have
an alternative and I'm therefore doing what I promised I'd do. Change
is tough, things may break but this is the right point to at least try
it.
I'd like to note that:
* setting up builds with a separate oe-core and bitbake clone
works as it always has done
* you can change your CI just to use those two repos instead of poky
* bitbake-setup isn't mandatory, it will just be what the yocto-
docs presents to users
* we don't have to stop maintaining the poky repository
however nobody will test the new approach/code unless we do
* we are optionally exposing sstate mirrors in the new config
* we are also exposing config fragments to users
* poky as a DISTRO in meta-yocto remains
A bit more about the history and background for those who are
interested and then some FAQs:
Back around 2010 when we split up openembedded-classic and started
developing layers, we made the artificial "poky" repository construct
as a way to let people easily and quickly get started with the project.
without cloning and managing multiple repositories. Layers were a new
idea with lots of rough edges. kas didn't exist, I think repo was only
just created and it was a different world. For us, it meant hacking up
a quick tool, "combo-layer" and it was really a temporary solution to
fill a gap and it was at least as functional as repo of the era. It was
assumed we'd work it out properly in the future.
At developer meetings there are inevitable questions about why
poky/combo-layer exist and few seem to actually like/support it. There
are continual questions about why a tool doesn't exist or why we don't
adopt one too.
15 years later, a bit longer than we might have thought, we are finally
in a position where there may be a viable way forward to change.
It has taken us a bit of time to get to this point. I wrote the
original description of something like bitbake-setup about 7-8 years
ago. I shared it privately with a few people, the review feedback
stopped me pushing it further as I simply did not have the bandwidth.
We were fortunate to get funding from the Sovereign Tech Fund to start
the work and whilst I'd probably prefer to avoid the issue, the time
had come to start. Since then, Alexander Kanavin has put a lot of work
into getting it to the point where it would be possible to switch. A
huge thanks to him for getting this to the current point.
Why not use kas/submodules/repo?
This topic has been discussed in depth several times. Very roughly,
these are either difficult to focus on our use cases or have specific
designs and intent which we as a project would struggle to influence.
We are taking significant influence from some of them but also trying
to build something where we can benefit from tight direct integration
with bitbake and the metadata. For example fragment support is generic
and hopefully something other approaches can also benefit from. We want
to provide something we can switch the projects docs and autobuilder to
which we can control and develop as we need it to. We are not aiming to
force anyone to switch, you can use whichever tool you want.
Can we not keep poky [repository master branch] around?
If we do that, nobody will use the new tooling and it will be a
disaster as issues won't get resolved. We need our CI to use the same
thing we promote to our new and experienced users. We need this new
tooling to be usable by our experienced developers too. We have tried
for months to get people to try it and they simply don't. Making a
release with it won't change much either. It needs people using it and
for that, poky has to stop being updated.
What happens to poky [repository]?
The LTS branches continue their lifetime as planned. For master, I'll
probably put a final commit in changing to just a README which points
people at the bitbake-setup changes and explains what happened.
What are the timelines? Why now?
If we're going to make a change, we really want this in the next LTS
release, which is April 2026. We only have one release before that
which is now, October 2025. We therefore need to switch now, and then
give us time to update docs, fix issues that arise and so on and have
it in a release cycle. Whilst it means delaying the Oct 2025 release
slightly, that is the right thing to do in the context of the bigger
picture.

5
bitbake/AUTHORS Normal file
View File

@@ -0,0 +1,5 @@
Holger Freyther <zecke@handhelds.org>
Chris Larson <kergoth@handhelds.org>
Mickey Lauer <mickey@Vanille.de>
Holger Schurig <holgerschurig@gmx.de>
Phil Blundell <pb@handhelds.org>

35
bitbake/ChangeLog Normal file
View File

@@ -0,0 +1,35 @@
Changes in BitBake 1.3.2:
- reintegration of make.py into BitBake
- bbread is gone, use bitbake -e
- lots of shell updates and bugfixes
- Introduction of the .= and =. operator
- Sort variables, keys and groups in bitdoc
- Fix regression in the handling of BBCOLLECTIONS
- Update the bitbake usermanual
Changes in BitBake 1.3.0:
- add bitbake interactive shell (bitbake -i)
- refactor bitbake utility in OO style
- kill default arguments in methods in the bb.data module
- kill default arguments in methods in the bb.fetch module
- the http/https/ftp fetcher will fail if the to be
downloaded file was not found in DL_DIR (this is needed
to avoid unpacking the sourceforge mirror page)
- Switch to a cow like data instance for persistent and non
persisting mode (called data_smart.py)
- Changed the callback of bb.make.collect_bbfiles to carry
additional parameters
- Drastically reduced the amount of needed RAM by not holding
each data instance in memory when using a cache/persistent
storage
Changes in BitBake 1.2.1:
The 1.2.1 release is meant as a intermediate release to lay the
ground for more radical changes. The most notable changes are:
- Do not hardcode {}, use bb.data.init() instead if you want to
get a instance of a data class
- bb.data.init() is a factory and the old bb.data methods are delegates
- Do not use deepcopy use bb.data.createCopy() instead.
- Removed default arguments in bb.fetch

27
bitbake/MANIFEST Normal file
View File

@@ -0,0 +1,27 @@
AUTHORS
ChangeLog
MANIFEST
setup.py
bin/bbimage
bin/bitbake
lib/bb/__init__.py
lib/bb/build.py
lib/bb/data.py
lib/bb/data_smart.py
lib/bb/event.py
lib/bb/fetch.py
lib/bb/manifest.py
lib/bb/parse/__init__.py
lib/bb/parse/parse_py/BBHandler.py
lib/bb/parse/parse_py/ConfHandler.py
lib/bb/parse/parse_py/__init__.py
lib/bb/shell.py
lib/bb/utils.py
doc/COPYING.GPL
doc/COPYING.MIT
doc/manual/html.css
doc/manual/Makefile
doc/manual/usermanual.xml
contrib/bbdev.sh
conf/bitbake.conf
classes/base.bbclass

18
bitbake/TODO Normal file
View File

@@ -0,0 +1,18 @@
On popular request by popular people a list of tasks to-do:
-Kill insecure usage of os.system either by properly escaping
the strings or a faster replacement not involving /bin/sh
-Introduce a -p option to automatically hotshot/profile the
run
-Cache dependencies separately and invalidate them when any file
changed.
-...
DONE:
<EFBFBD> -On generating the inter package deps do not parse each file multiply
<EFBFBD> times.
-We build the lists while parsing the data now
<EFBFBD> (WAS: Do not generate the world dependency tree, only when someone
<EFBFBD> requests it.

154
bitbake/bin/bbimage Executable file
View File

@@ -0,0 +1,154 @@
#!/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) 2003 Chris Larson
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
import sys, os
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb
from bb import *
__version__ = 1.0
type = "jffs2"
cfg_bb = data.init()
cfg_oespawn = data.init()
def usage():
print "Usage: bbimage [options ...]"
print "Creates an image for a target device from a root filesystem,"
print "obeying configuration parameters from the BitBake"
print "configuration files, thereby easing handling of deviceisms."
print ""
print " %s\t\t%s" % ("-r [arg], --root [arg]", "root directory (default=${IMAGE_ROOTFS})")
print " %s\t\t%s" % ("-t [arg], --type [arg]", "image type (jffs2[default], cramfs)")
print " %s\t\t%s" % ("-n [arg], --name [arg]", "image name (override IMAGE_NAME variable)")
print " %s\t\t%s" % ("-v, --version", "output version information and exit")
sys.exit(0)
def version():
print "BitBake Build Tool Core version %s" % bb.__version__
print "BBImage version %s" % __version__
def emit_bb(d, base_d = {}):
for v in d.keys():
if d[v] != base_d[v]:
data.emit_var(v, d)
def getopthash(l):
h = {}
for (opt, val) in l:
h[opt] = val
return h
import getopt
try:
(opts, args) = getopt.getopt(sys.argv[1:], 'vr:t:e:n:', [ 'version', 'root=', 'type=', 'bbfile=', 'name=' ])
except getopt.GetoptError:
usage()
# handle opts
opthash = getopthash(opts)
if '--version' in opthash or '-v' in opthash:
version()
sys.exit(0)
try:
cfg_bb = parse.handle(os.path.join('conf', 'bitbake.conf'), cfg_bb)
except IOError:
fatal("Unable to open bitbake.conf")
# sanity check
if cfg_bb is None:
fatal("Unable to open/parse %s" % os.path.join('conf', 'bitbake.conf'))
usage(1)
rootfs = None
extra_files = []
if '--root' in opthash:
rootfs = opthash['--root']
if '-r' in opthash:
rootfs = opthash['-r']
if '--type' in opthash:
type = opthash['--type']
if '-t' in opthash:
type = opthash['-t']
if '--bbfile' in opthash:
extra_files.append(opthash['--bbfile'])
if '-e' in opthash:
extra_files.append(opthash['-e'])
for f in extra_files:
try:
cfg_bb = parse.handle(f, cfg_bb)
except IOError:
print "unable to open %s" % f
if not rootfs:
rootfs = data.getVar('IMAGE_ROOTFS', cfg_bb, 1)
if not rootfs:
bb.fatal("IMAGE_ROOTFS not defined")
data.setVar('IMAGE_ROOTFS', rootfs, cfg_bb)
from copy import copy, deepcopy
localdata = data.createCopy(cfg_bb)
overrides = data.getVar('OVERRIDES', localdata)
if not overrides:
bb.fatal("OVERRIDES not defined.")
data.setVar('OVERRIDES', '%s:%s' % (overrides, type), localdata)
data.update_data(localdata)
data.setVar('OVERRIDES', overrides, localdata)
if '-n' in opthash:
data.setVar('IMAGE_NAME', opthash['-n'], localdata)
if '--name' in opthash:
data.setVar('IMAGE_NAME', opthash['--name'], localdata)
topdir = data.getVar('TOPDIR', localdata, 1) or os.getcwd()
cmd = data.getVar('IMAGE_CMD', localdata, 1)
if not cmd:
bb.fatal("IMAGE_CMD not defined")
outdir = data.getVar('DEPLOY_DIR_IMAGE', localdata, 1)
if not outdir:
bb.fatal('DEPLOY_DIR_IMAGE not defined')
mkdirhier(outdir)
#depends = data.getVar('IMAGE_DEPENDS', localdata, 1) or ""
#if depends:
# bb.note("Spawning bbmake to satisfy dependencies: %s" % depends)
# ret = os.system('bbmake %s' % depends)
# if ret != 0:
# bb.error("executing bbmake to satisfy dependencies")
bb.note("Executing %s" % cmd)
data.setVar('image_cmd', cmd, localdata)
data.setVarFlag('image_cmd', 'func', 1, localdata)
try:
bb.build.exec_func('image_cmd', localdata)
except bb.build.FuncFailed:
sys.exit(1)
#ret = os.system(cmd)
#sys.exit(ret)

933
bitbake/bin/bitbake Executable file
View File

@@ -0,0 +1,933 @@
#!/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) 2003, 2004 Chris Larson
# Copyright (C) 2003, 2004 Phil Blundell
# Copyright (C) 2003 - 2005 Michael 'Mickey' Lauer
# Copyright (C) 2005 Holger Hans Peter Freyther
# Copyright (C) 2005 ROAD GmbH
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
import sys, os, getopt, glob, copy, os.path, re, time
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb
from bb import utils, data, parse, debug, event, fatal
from sets import Set
import itertools, optparse
parsespin = itertools.cycle( r'|/-\\' )
bbdebug = 0
__version__ = "1.3.2"
#============================================================================#
# BBParsingStatus
#============================================================================#
class BBParsingStatus:
"""
The initial idea for this status class is to use the data when it is
already loaded instead of loading it from various place over and over
again.
"""
def __init__(self):
self.cache_dirty = False
self.providers = {}
self.bbfile_priority = {}
self.bbfile_config_priorities = []
self.ignored_depedencies = None
self.possible_world = []
self.world_target = Set()
self.pkg_pn = {}
self.pkg_fn = {}
self.pkg_pvpr = {}
self.pkg_dp = {}
self.pn_provides = {}
self.all_depends = Set()
def handle_bb_data(self, file_name, bb_data, cached):
"""
We will fill the dictionaries with the stuff we
need for building the tree more fast
"""
if bb_data == None:
return
if not cached:
self.cache_dirty = True
pn = bb.data.getVar('PN', bb_data, True)
pv = bb.data.getVar('PV', bb_data, True)
pr = bb.data.getVar('PR', bb_data, True)
dp = int(bb.data.getVar('DEFAULT_PREFERENCE', bb_data, True) or "0")
provides = Set([pn] + (bb.data.getVar("PROVIDES", bb_data, 1) or "").split())
depends = (bb.data.getVar("DEPENDS", bb_data, True) or "").split()
# build PackageName to FileName lookup table
if pn not in self.pkg_pn:
self.pkg_pn[pn] = []
self.pkg_pn[pn].append(file_name)
# build FileName to PackageName lookup table
self.pkg_fn[file_name] = pn
self.pkg_pvpr[file_name] = (pv,pr)
self.pkg_dp[file_name] = dp
# Build forward and reverse provider hashes
# Forward: virtual -> [filenames]
# Reverse: PN -> [virtuals]
if pn not in self.pn_provides:
self.pn_provides[pn] = Set()
self.pn_provides[pn] |= provides
for provide in provides:
if provide not in self.providers:
self.providers[provide] = []
self.providers[provide].append(file_name)
for dep in depends:
self.all_depends.add(dep)
# Collect files we may need for possible world-dep
# calculations
if not bb.data.getVar('BROKEN', bb_data, True) and not bb.data.getVar('EXCLUDE_FROM_WORLD', bb_data, True):
self.possible_world.append(file_name)
#============================================================================#
# BBStatistics
#============================================================================#
class BBStatistics:
"""
Manage build statistics for one run
"""
def __init__(self ):
self.attempt = 0
self.success = 0
self.fail = 0
self.deps = 0
def show( self ):
print "Build statistics:"
print " Attempted builds: %d" % self.attempt
if self.fail:
print " Failed builds: %d" % self.fail
if self.deps:
print " Dependencies not satisfied: %d" % self.deps
if self.fail or self.deps: return 1
else: return 0
#============================================================================#
# BBOptions
#============================================================================#
class BBConfiguration( object ):
"""
Manages build options and configurations for one run
"""
def __init__( self, options ):
for key, val in options.__dict__.items():
setattr( self, key, val )
self.data = data.init()
#============================================================================#
# BBCooker
#============================================================================#
class BBCooker:
"""
Manages one bitbake build run
"""
ParsingStatus = BBParsingStatus # make it visible from the shell
Statistics = BBStatistics # make it visible from the shell
def __init__( self ):
self.build_cache_fail = []
self.build_cache = []
self.building_list = []
self.build_path = []
self.consider_msgs_cache = []
self.preferred = {}
self.stats = BBStatistics()
self.status = None
self.pkgdata = None
self.cache = None
def tryBuildPackage( self, fn, item, the_data ):
"""Build one package"""
bb.event.fire(bb.event.PkgStarted(item, the_data))
try:
self.stats.attempt += 1
if self.configuration.force:
bb.data.setVarFlag('do_%s' % self.configuration.cmd, 'force', 1, the_data)
if not self.configuration.dry_run:
bb.build.exec_task('do_%s' % self.configuration.cmd, the_data)
bb.event.fire(bb.event.PkgSucceeded(item, the_data))
self.build_cache.append(fn)
return True
except bb.build.FuncFailed:
self.stats.fail += 1
bb.error("task stack execution failed")
bb.event.fire(bb.event.PkgFailed(item, the_data))
self.build_cache_fail.append(fn)
raise
except bb.build.EventException, e:
self.stats.fail += 1
event = e.args[1]
bb.error("%s event exception, aborting" % bb.event.getName(event))
bb.event.fire(bb.event.PkgFailed(item, the_data))
self.build_cache_fail.append(fn)
raise
def tryBuild( self, fn, virtual ):
"""Build a provider and its dependencies"""
if fn in self.building_list:
bb.error("%s depends on itself (eventually)" % fn)
bb.error("upwards chain is: %s" % (" -> ".join(self.build_path)))
return False
the_data = self.pkgdata[fn]
item = self.status.pkg_fn[fn]
self.building_list.append(fn)
pathstr = "%s (%s)" % (item, virtual)
self.build_path.append(pathstr)
depends_list = (bb.data.getVar('DEPENDS', the_data, 1) or "").split()
if self.configuration.verbose:
bb.note("current path: %s" % (" -> ".join(self.build_path)))
bb.note("dependencies for %s are: %s" % (item, " ".join(depends_list)))
try:
failed = False
depcmd = self.configuration.cmd
bbdepcmd = bb.data.getVarFlag('do_%s' % self.configuration.cmd, 'bbdepcmd', the_data)
if bbdepcmd is not None:
if bbdepcmd == "":
depcmd = None
else:
depcmd = bbdepcmd
if depcmd:
oldcmd = self.configuration.cmd
self.configuration.cmd = depcmd
for dependency in depends_list:
if dependency in self.status.ignored_dependencies:
continue
if not depcmd:
continue
if self.buildProvider( dependency ) == 0:
bb.error("dependency %s (for %s) not satisfied" % (dependency,item))
failed = True
if self.configuration.abort:
break
if depcmd:
self.configuration.cmd = oldcmd
if failed:
self.stats.deps += 1
return False
if bb.build.stamp_is_current('do_%s' % self.configuration.cmd, the_data):
self.build_cache.append(fn)
return True
return self.tryBuildPackage( fn, item, the_data )
finally:
self.building_list.remove(fn)
self.build_path.remove(pathstr)
def findBestProvider( self, pn, pkg_pn = None):
"""
If there is a PREFERRED_VERSION, find the highest-priority bbfile
providing that version. If not, find the latest version provided by
an bbfile in the highest-priority set.
"""
if not pkg_pn:
pkg_pn = self.status.pkg_pn
files = pkg_pn[pn]
priorities = {}
for f in files:
priority = self.status.bbfile_priority[f]
if priority not in priorities:
priorities[priority] = []
priorities[priority].append(f)
p_list = priorities.keys()
p_list.sort(lambda a, b: a - b)
tmp_pn = []
for p in p_list:
tmp_pn = [priorities[p]] + tmp_pn
preferred_file = None
localdata = data.createCopy(self.configuration.data)
bb.data.setVar('OVERRIDES', "%s:%s" % (pn, data.getVar('OVERRIDES', localdata)), localdata)
bb.data.update_data(localdata)
preferred_v = bb.data.getVar('PREFERRED_VERSION_%s' % pn, localdata, 1)
if preferred_v:
m = re.match('(.*)_(.*)', preferred_v)
if m:
preferred_v = m.group(1)
preferred_r = m.group(2)
else:
preferred_r = None
for file_set in tmp_pn:
for f in file_set:
pv,pr = self.status.pkg_pvpr[f]
if preferred_v == pv and (preferred_r == pr or preferred_r == None):
preferred_file = f
preferred_ver = (pv, pr)
break
if preferred_file:
break;
if preferred_r:
pv_str = '%s-%s' % (preferred_v, preferred_r)
else:
pv_str = preferred_v
if preferred_file is None:
bb.note("preferred version %s of %s not available" % (pv_str, pn))
else:
bb.debug(1, "selecting %s as PREFERRED_VERSION %s of package %s" % (preferred_file, pv_str, pn))
del localdata
# get highest priority file set
files = tmp_pn[0]
latest = None
latest_p = 0
latest_f = None
for file_name in files:
pv,pr = self.status.pkg_pvpr[file_name]
dp = self.status.pkg_dp[file_name]
if (latest is None) or ((latest_p == dp) and (utils.vercmp(latest, (pv, pr)) < 0)) or (dp > latest_p):
latest = (pv, pr)
latest_f = file_name
latest_p = dp
if preferred_file is None:
preferred_file = latest_f
preferred_ver = latest
return (latest,latest_f,preferred_ver, preferred_file)
def showVersions( self ):
pkg_pn = self.status.pkg_pn
preferred_versions = {}
latest_versions = {}
# Sort by priority
for pn in pkg_pn.keys():
(last_ver,last_file,pref_ver,pref_file) = self.findBestProvider(pn)
preferred_versions[pn] = (pref_ver, pref_file)
latest_versions[pn] = (last_ver, last_file)
pkg_list = pkg_pn.keys()
pkg_list.sort()
for p in pkg_list:
pref = preferred_versions[p]
latest = latest_versions[p]
if pref != latest:
prefstr = pref[0][0] + "-" + pref[0][1]
else:
prefstr = ""
print "%-30s %20s %20s" % (p, latest[0][0] + "-" + latest[0][1],
prefstr)
def showEnvironment( self ):
"""Show the outer or per-package environment"""
if self.configuration.buildfile:
try:
self.configuration.data, fromCache = self.load_bbfile( self.configuration.buildfile )
except IOError, e:
fatal("Unable to read %s: %s" % ( self.configuration.buildfile, e ))
except Exception, e:
fatal("%s" % e)
# emit variables and shell functions
try:
data.update_data( self.configuration.data )
data.emit_env(sys.__stdout__, self.configuration.data, True)
except Exception, e:
fatal("%s" % e)
# emit the metadata which isnt valid shell
for e in self.configuration.data.keys():
if data.getVarFlag( e, 'python', self.configuration.data ):
sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, data.getVar(e, self.configuration.data, 1)))
def buildProvider( self, item ):
fn = None
discriminated = False
if item not in self.status.providers:
bb.error("Nothing provides %s" % item)
return 0
all_p = self.status.providers[item]
for p in all_p:
if p in self.build_cache:
bb.debug(1, "already built %s in this run\n" % p)
return 1
eligible = []
preferred_versions = {}
# Collate providers by PN
pkg_pn = {}
for p in all_p:
pn = self.status.pkg_fn[p]
if pn not in pkg_pn:
pkg_pn[pn] = []
pkg_pn[pn].append(p)
bb.debug(1, "providers for %s are: %s" % (item, pkg_pn.keys()))
for pn in pkg_pn.keys():
preferred_versions[pn] = self.findBestProvider(pn, pkg_pn)[2:4]
eligible.append(preferred_versions[pn][1])
for p in eligible:
if p in self.build_cache_fail:
bb.debug(1, "rejecting already-failed %s" % p)
eligible.remove(p)
if len(eligible) == 0:
bb.error("no eligible providers for %s" % item)
return 0
# look to see if one of them is already staged, or marked as preferred.
# if so, bump it to the head of the queue
for p in all_p:
the_data = self.pkgdata[p]
pn = bb.data.getVar('PN', the_data, 1)
pv = bb.data.getVar('PV', the_data, 1)
pr = bb.data.getVar('PR', the_data, 1)
tmpdir = bb.data.getVar('TMPDIR', the_data, 1)
stamp = '%s/stamps/%s-%s-%s.do_populate_staging' % (tmpdir, pn, pv, pr)
if os.path.exists(stamp):
(newvers, fn) = preferred_versions[pn]
if not fn in eligible:
# package was made ineligible by already-failed check
continue
oldver = "%s-%s" % (pv, pr)
newver = '-'.join(newvers)
if (newver != oldver):
extra_chat = "; upgrading from %s to %s" % (oldver, newver)
else:
extra_chat = ""
if self.configuration.verbose:
bb.note("selecting already-staged %s to satisfy %s%s" % (pn, item, extra_chat))
eligible.remove(fn)
eligible = [fn] + eligible
discriminated = True
break
prefervar = bb.data.getVar('PREFERRED_PROVIDER_%s' % item, self.configuration.data, 1)
if prefervar:
self.preferred[item] = prefervar
if item in self.preferred:
for p in eligible:
pn = self.status.pkg_fn[p]
if self.preferred[item] == pn:
if self.configuration.verbose:
bb.note("selecting %s to satisfy %s due to PREFERRED_PROVIDERS" % (pn, item))
eligible.remove(p)
eligible = [p] + eligible
discriminated = True
break
if len(eligible) > 1 and discriminated == False:
if item not in self.consider_msgs_cache:
providers_list = []
for fn in eligible:
providers_list.append(self.status.pkg_fn[fn])
bb.note("multiple providers are available (%s);" % ", ".join(providers_list))
bb.note("consider defining PREFERRED_PROVIDER_%s" % item)
self.consider_msgs_cache.append(item)
# run through the list until we find one that we can build
for fn in eligible:
bb.debug(2, "selecting %s to satisfy %s" % (fn, item))
if self.tryBuild(fn, item):
return 1
bb.note("no buildable providers for %s" % item)
return 0
def buildDepgraph( self ):
all_depends = self.status.all_depends
pn_provides = self.status.pn_provides
def calc_bbfile_priority(filename):
for (regex, pri) in self.status.bbfile_config_priorities:
if regex.match(filename):
return pri
return 0
# Handle PREFERRED_PROVIDERS
for p in (bb.data.getVar('PREFERRED_PROVIDERS', self.configuration.data, 1) or "").split():
(providee, provider) = p.split(':')
if providee in self.preferred and self.preferred[providee] != provider:
bb.error("conflicting preferences for %s: both %s and %s specified" % (providee, provider, self.preferred[providee]))
self.preferred[providee] = provider
# Calculate priorities for each file
for p in self.pkgdata.keys():
self.status.bbfile_priority[p] = calc_bbfile_priority(p)
# Build package list for "bitbake world"
bb.debug(1, "collating packages for \"world\"")
for f in self.status.possible_world:
terminal = True
pn = self.status.pkg_fn[f]
for p in pn_provides[pn]:
if p.startswith('virtual/'):
bb.debug(2, "skipping %s due to %s provider starting with virtual/" % (f, p))
terminal = False
break
for pf in self.status.providers[p]:
if self.status.pkg_fn[pf] != pn:
bb.debug(2, "skipping %s due to both us and %s providing %s" % (f, pf, p))
terminal = False
break
if terminal:
self.status.world_target.add(pn)
# drop reference count now
self.status.possible_world = None
self.status.all_depends = None
def myProgressCallback( self, x, y, f, file_data, from_cache ):
# feed the status with new input
self.status.handle_bb_data(f, file_data, from_cache)
if bbdebug > 0:
return
if os.isatty(sys.stdout.fileno()):
sys.stdout.write("\rNOTE: Handling BitBake files: %s (%04d/%04d) [%2d %%]" % ( parsespin.next(), x, y, x*100/y ) )
sys.stdout.flush()
else:
if x == 1:
sys.stdout.write("Parsing .bb files, please wait...")
sys.stdout.flush()
if x == y:
sys.stdout.write("done.")
sys.stdout.flush()
def interactiveMode( self ):
"""Drop off into a shell"""
try:
from bb import shell
except ImportError, details:
bb.fatal("Sorry, shell not available (%s)" % details )
else:
bb.data.update_data( self.configuration.data )
shell.start( self )
sys.exit( 0 )
def parseConfigurationFile( self, afile ):
try:
self.configuration.data = bb.parse.handle( afile, self.configuration.data )
except IOError:
bb.fatal( "Unable to open %s" % afile )
except bb.parse.ParseError, details:
bb.fatal( "Unable to parse %s (%s)" % (afile, details) )
def handleCollections( self, collections ):
"""Handle collections"""
if collections:
collection_list = collections.split()
for c in collection_list:
regex = bb.data.getVar("BBFILE_PATTERN_%s" % c, self.configuration.data, 1)
if regex == None:
bb.error("BBFILE_PATTERN_%s not defined" % c)
continue
priority = bb.data.getVar("BBFILE_PRIORITY_%s" % c, self.configuration.data, 1)
if priority == None:
bb.error("BBFILE_PRIORITY_%s not defined" % c)
continue
try:
cre = re.compile(regex)
except re.error:
bb.error("BBFILE_PATTERN_%s \"%s\" is not a valid regular expression" % (c, regex))
continue
try:
pri = int(priority)
self.status.bbfile_config_priorities.append((cre, pri))
except ValueError:
bb.error("invalid value for BBFILE_PRIORITY_%s: \"%s\"" % (c, priority))
def cook( self, configuration, args ):
self.configuration = configuration
if not self.configuration.cmd:
self.configuration.cmd = "build"
if self.configuration.debug:
bb.debug_level = self.configuration.debug
self.configuration.data = bb.data.init()
for f in self.configuration.file:
self.parseConfigurationFile( f )
self.parseConfigurationFile( os.path.join( "conf", "bitbake.conf" ) )
if self.configuration.show_environment:
self.showEnvironment()
sys.exit( 0 )
# inject custom variables
if not bb.data.getVar("BUILDNAME", self.configuration.data):
bb.data.setVar("BUILDNAME", os.popen('date +%Y%m%d%H%M').readline().strip(), self.configuration.data)
bb.data.setVar("BUILDSTART", time.strftime('%m/%d/%Y %H:%M:%S',time.gmtime()),self.configuration.data)
buildname = bb.data.getVar("BUILDNAME", self.configuration.data)
if self.configuration.interactive:
self.interactiveMode()
if self.configuration.buildfile is not None:
bf = os.path.abspath( self.configuration.buildfile )
try:
bbfile_data = bb.parse.handle(bf, self.configuration.data)
except IOError:
bb.fatal("Unable to open %s" % bf)
item = bb.data.getVar('PN', bbfile_data, 1)
try:
self.tryBuildPackage( bf, item, bbfile_data )
except bb.build.EventException:
bb.error( "Build of '%s' failed" % item )
sys.exit( self.stats.show() )
# initialise the parsing status now we know we will need deps
self.status = BBParsingStatus()
ignore = bb.data.getVar("ASSUME_PROVIDED", self.configuration.data, 1) or ""
self.status.ignored_dependencies = Set( ignore.split() )
self.handleCollections( bb.data.getVar("BBFILE_COLLECTIONS", self.configuration.data, 1) )
pkgs_to_build = None
if args:
if not pkgs_to_build:
pkgs_to_build = []
pkgs_to_build.extend(args)
if not pkgs_to_build:
bbpkgs = bb.data.getVar('BBPKGS', self.configuration.data, 1)
if bbpkgs:
pkgs_to_build = bbpkgs.split()
if not pkgs_to_build and not self.configuration.show_versions \
and not self.configuration.interactive \
and not self.configuration.show_environment:
print "Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help'"
print "for usage information."
sys.exit(0)
# Import Psyco if available and not disabled
if not self.configuration.disable_psyco:
try:
import psyco
except ImportError:
if bbdebug == 0:
bb.note("Psyco JIT Compiler (http://psyco.sf.net) not available. Install it to increase performance.")
else:
psyco.bind( self.collect_bbfiles )
else:
bb.note("You have disabled Psyco. This decreases performance.")
try:
bb.debug(1, "collecting .bb files")
self.collect_bbfiles( self.myProgressCallback )
bb.debug(1, "parsing complete")
if bbdebug == 0:
print
if self.configuration.parse_only:
print "Requested parsing .bb files only. Exiting."
return
bb.data.update_data( self.configuration.data )
self.buildDepgraph()
if self.configuration.show_versions:
self.showVersions()
sys.exit( 0 )
if 'world' in pkgs_to_build:
pkgs_to_build.remove('world')
for t in self.status.world_target:
pkgs_to_build.append(t)
bb.event.fire(bb.event.BuildStarted(buildname, pkgs_to_build, self.configuration.data))
for k in pkgs_to_build:
failed = False
try:
if self.buildProvider( k ) == 0:
# already diagnosed
failed = True
except bb.build.EventException:
bb.error("Build of " + k + " failed")
failed = True
if failed:
if self.configuration.abort:
sys.exit(1)
bb.event.fire(bb.event.BuildCompleted(buildname, pkgs_to_build, self.configuration.data))
sys.exit( self.stats.show() )
except KeyboardInterrupt:
print "\nNOTE: KeyboardInterrupt - Build not completed."
sys.exit(1)
def get_bbfiles( self, path = os.getcwd() ):
"""Get list of default .bb files by reading out the current directory"""
contents = os.listdir(path)
bbfiles = []
for f in contents:
(root, ext) = os.path.splitext(f)
if ext == ".bb":
bbfiles.append(os.path.abspath(os.path.join(os.getcwd(),f)))
return bbfiles
def find_bbfiles( self, path ):
"""Find all the .bb files in a directory (uses find)"""
findcmd = 'find ' + path + ' -name *.bb | grep -v SCCS/'
try:
finddata = os.popen(findcmd)
except OSError:
return []
return finddata.readlines()
def deps_clean(self, d):
depstr = data.getVar('__depends', d)
if depstr:
deps = depstr.split(" ")
for dep in deps:
(f,old_mtime_s) = dep.split("@")
old_mtime = int(old_mtime_s)
new_mtime = parse.cached_mtime(f)
if (new_mtime > old_mtime):
return False
return True
def load_bbfile( self, bbfile ):
"""Load and parse one .bb build file"""
if not self.cache in [None, '']:
# get the times
cache_mtime = data.init_db_mtime(self.cache, bbfile)
file_mtime = parse.cached_mtime(bbfile)
if file_mtime > cache_mtime:
#print " : '%s' dirty. reparsing..." % bbfile
pass
else:
#print " : '%s' clean. loading from cache..." % bbfile
cache_data = data.init_db( self.cache, bbfile, False )
if self.deps_clean(cache_data):
return cache_data, True
topdir = data.getVar('TOPDIR', self.configuration.data)
if not topdir:
topdir = os.path.abspath(os.getcwd())
# set topdir to here
data.setVar('TOPDIR', topdir, self.configuration)
bbfile = os.path.abspath(bbfile)
bbfile_loc = os.path.abspath(os.path.dirname(bbfile))
# expand tmpdir to include this topdir
data.setVar('TMPDIR', data.getVar('TMPDIR', self.configuration.data, 1) or "", self.configuration.data)
# set topdir to location of .bb file
topdir = bbfile_loc
#data.setVar('TOPDIR', topdir, cfg)
# go there
oldpath = os.path.abspath(os.getcwd())
os.chdir(topdir)
bb = data.init_db(self.cache,bbfile, True, self.configuration.data)
try:
parse.handle(bbfile, bb) # read .bb data
if not self.cache in [None, '']:
bb.commit(parse.cached_mtime(bbfile)) # write cache
os.chdir(oldpath)
return bb, False
finally:
os.chdir(oldpath)
def collect_bbfiles( self, progressCallback ):
"""Collect all available .bb build files"""
self.cb = progressCallback
parsed, cached, skipped, masked = 0, 0, 0, 0
self.cache = bb.data.getVar( "CACHE", self.configuration.data, 1 )
self.pkgdata = data.pkgdata( not self.cache in [None, ''], self.cache, self.configuration.data )
if not self.cache in [None, '']:
if self.cb is not None:
print "NOTE: Using cache in '%s'" % self.cache
try:
os.stat( self.cache )
except OSError:
bb.mkdirhier( self.cache )
else:
if self.cb is not None:
print "NOTE: Not using a cache. Set CACHE = <directory> to enable."
files = (data.getVar( "BBFILES", self.configuration.data, 1 ) or "").split()
data.setVar("BBFILES", " ".join(files), self.configuration.data)
if not len(files):
files = self.get_bbfiles()
if not len(files):
bb.error("no files to build.")
newfiles = []
for f in files:
if os.path.isdir(f):
dirfiles = self.find_bbfiles(f)
if dirfiles:
newfiles += dirfiles
continue
newfiles += glob.glob(f) or [ f ]
bbmask = bb.data.getVar('BBMASK', self.configuration.data, 1) or ""
try:
bbmask_compiled = re.compile(bbmask)
except sre_constants.error:
bb.fatal("BBMASK is not a valid regular expression.")
for i in xrange( len( newfiles ) ):
f = newfiles[i]
if bbmask and bbmask_compiled.search(f):
bb.debug(1, "bbmake: skipping %s" % f)
masked += 1
continue
debug(1, "bbmake: parsing %s" % f)
# read a file's metadata
try:
bb_data, fromCache = self.load_bbfile(f)
if fromCache: cached += 1
else: parsed += 1
deps = None
if bb_data is not None:
# allow metadata files to add items to BBFILES
#data.update_data(self.pkgdata[f])
addbbfiles = data.getVar('BBFILES', bb_data) or None
if addbbfiles:
for aof in addbbfiles.split():
if not files.count(aof):
if not os.path.isabs(aof):
aof = os.path.join(os.path.dirname(f),aof)
files.append(aof)
for var in bb_data.keys():
if data.getVarFlag(var, "handler", bb_data) and data.getVar(var, bb_data):
event.register(data.getVar(var, bb_data))
self.pkgdata[f] = bb_data
# now inform the caller
if self.cb is not None:
self.cb( i + 1, len( newfiles ), f, bb_data, fromCache )
except IOError, e:
bb.error("opening %s: %s" % (f, e))
pass
except bb.parse.SkipPackage:
skipped += 1
pass
except KeyboardInterrupt:
raise
except Exception, e:
bb.error("%s while parsing %s" % (e, f))
if self.cb is not None:
print "\rNOTE: Parsing finished. %d cached, %d parsed, %d skipped, %d masked." % ( cached, parsed, skipped, masked ),
#============================================================================#
# main
#============================================================================#
if __name__ == "__main__":
parser = optparse.OptionParser( version = "BitBake Build Tool Core version %s, %%prog version %s" % ( bb.__version__, __version__ ),
usage = """%prog [options] [package ...]
Executes the specified task (default is 'build') for a given set of BitBake files.
It expects that BBFILES is defined, which is a space seperated list of files to
be executed. BBFILES does support wildcards.
Default BBFILES are the .bb files in the current directory.""" )
parser.add_option( "-b", "--buildfile", help = "execute the task against this .bb file, rather than a package from BBFILES.",
action = "store", dest = "buildfile", default = None )
parser.add_option( "-k", "--continue", help = "continue as much as possible after an error. While the target that failed, and those that depend on it, cannot be remade, the other dependencies of these targets can be processed all the same.",
action = "store_false", dest = "abort", default = True )
parser.add_option( "-f", "--force", help = "force run of specified cmd, regardless of stamp status",
action = "store_true", dest = "force", default = False )
parser.add_option( "-i", "--interactive", help = "drop into the interactive mode.",
action = "store_true", dest = "interactive", default = False )
parser.add_option( "-c", "--cmd", help = "Specify task to execute. Note that this only executes the specified task for the providee and the packages it depends on, i.e. 'compile' does not implicitly call stage for the dependencies (IOW: use only if you know what you are doing)",
action = "store", dest = "cmd", default = "build" )
parser.add_option( "-r", "--read", help = "read the specified file before bitbake.conf",
action = "append", dest = "file", default = [] )
parser.add_option( "-v", "--verbose", help = "output more chit-chat to the terminal",
action = "store_true", dest = "verbose", default = False )
parser.add_option( "-D", "--debug", help = "Increase the debug level",
action = "count", dest="debug", default = 0)
parser.add_option( "-n", "--dry-run", help = "don't execute, just go through the motions",
action = "store_true", dest = "dry_run", default = False )
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( "-d", "--disable-psyco", help = "disable using the psyco just-in-time compiler (not recommended)",
action = "store_true", dest = "disable_psyco", default = False )
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)",
action = "store_true", dest = "show_environment", default = False )
options, args = parser.parse_args( sys.argv )
cooker = BBCooker()
cooker.cook( BBConfiguration( options ), args[1:] )

BIN
bitbake/bin/bitbakec Normal file

Binary file not shown.

529
bitbake/bin/bitdoc Executable file
View File

@@ -0,0 +1,529 @@
#!/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) 2005 Holger Hans Peter Freyther
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
# SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
# THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
#
import optparse, os, sys
# bitbake
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(sys.argv[0])), 'lib'))
import bb
from bb import make
from string import split, join
__version__ = "0.0.2"
class HTMLFormatter:
"""
Simple class to help to generate some sort of HTML files. It is
quite inferior solution compared to docbook, gtkdoc, doxygen but it
should work for now.
We've a global introduction site (index.html) and then one site for
the list of keys (alphabetical sorted) and one for the list of groups,
one site for each key with links to the relations and groups.
index.html
keys.html
groups.html
groupNAME.html
keyNAME.html
"""
def replace(self, text, *pairs):
"""
From pydoc... almost identical at least
"""
while pairs:
(a,b) = pairs[0]
text = join(split(text, a), b)
pairs = pairs[1:]
return text
def escape(self, text):
"""
Escape string to be conform HTML
"""
return self.replace(text,
('&', '&amp;'),
('<', '&lt;' ),
('>', '&gt;' ) )
def createNavigator(self):
"""
Create the navgiator
"""
return """<table class="navigation" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2">
<tr valign="middle">
<td><a accesskey="g" href="index.html">Home</a></td>
<td><a accesskey="n" href="groups.html">Groups</a></td>
<td><a accesskey="u" href="keys.html">Keys</a></td>
</tr></table>
"""
def relatedKeys(self, item):
"""
Create HTML to link to foreign keys
"""
if len(item.related()) == 0:
return ""
txt = "<p><b>See also:</b><br>"
for it in item.related():
txt += """<a href="key%s.html">%s</a>, """ % (it, it)
return txt
def groups(self,item):
"""
Create HTML to link to related groups
"""
if len(item.groups()) == 0:
return ""
txt = "<p><b>Seel also:</b><br>"
for group in item.groups():
txt += """<a href="group%s.html">%s</a>, """ % (group,group)
return txt
def createKeySite(self,item):
"""
Create a site for a key. It contains the header/navigator, a heading,
the description, links to related keys and to the groups.
"""
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Key %s</title></head>
<link rel="stylesheet" href="style.css" type="text/css">
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
%s
<h2><span class="refentrytitle">%s</span></h2>
<div class="refsynopsisdiv">
<h2>Synopsis</h2>
<pre class="synopsis">
%s
</pre>
</div>
<div class="refsynopsisdiv">
<h2>Related Keys</h2>
<pre class="synopsis">
%s
</pre>
</div>
<div class="refsynopsisdiv">
<h2>Groups</h2>
<pre class="synopsis">
%s
</pre>
</div>
</body>
""" % (item.name(), self.createNavigator(), item.name(),
self.escape(item.description()), self.relatedKeys(item), self.groups(item))
def createGroupsSite(self, doc):
"""
Create the Group Overview site
"""
groups = ""
sorted_groups = doc.groups()
sorted_groups.sort()
for group in sorted_groups:
groups += """<a href="group%s.html">%s</a><br>""" % (group, group)
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Group overview</title></head>
<link rel="stylesheet" href="style.css" type="text/css">
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
%s
<h2>Available Groups</h2>
%s
</body>
""" % (self.createNavigator(), groups)
def createIndex(self):
"""
Create the index file
"""
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Bitbake Documentation</title></head>
<link rel="stylesheet" href="style.css" type="text/css">
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
%s
<h2>Documentation Entrance</h2>
<a href="groups.html">All available groups</a><br>
<a href="keys.html">All available keys</a><br>
</body>
""" % self.createNavigator()
def createKeysSite(self, doc):
"""
Create Overview of all avilable keys
"""
keys = ""
sorted_keys = doc.doc_keys()
sorted_keys.sort()
for key in sorted_keys:
keys += """<a href="key%s.html">%s</a><br>""" % (key, key)
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Key overview</title></head>
<link rel="stylesheet" href="style.css" type="text/css">
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
%s
<h2>Available Keys</h2>
%s
</body>
""" % (self.createNavigator(), keys)
def createGroupSite(self,gr, items):
"""
Create a site for a group:
Group the name of the group, items contain the name of the keys
inside this group
"""
groups = ""
for group in items:
groups += """<a href="key%s.html">%s</a><br>""" % (group.name(), group.name())
return """<!doctype html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Group %s</title></head>
<link rel="stylesheet" href="style.css" type="text/css">
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
%s
<div class="refsynopsisdiv">
<h2>Keys in Group %s</h2>
<pre class="synopsis">
%s
</pre>
</div>
</body>
""" % (gr, self.createNavigator(), gr, groups)
def createCSS(self):
"""
Create the CSS file
"""
return """.synopsis, .classsynopsis
{
background: #eeeeee;
border: solid 1px #aaaaaa;
padding: 0.5em;
}
.programlisting
{
background: #eeeeff;
border: solid 1px #aaaaff;
padding: 0.5em;
}
.variablelist
{
padding: 4px;
margin-left: 3em;
}
.variablelist td:first-child
{
vertical-align: top;
}
table.navigation
{
background: #ffeeee;
border: solid 1px #ffaaaa;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.navigation a
{
color: #770000;
}
.navigation a:visited
{
color: #550000;
}
.navigation .title
{
font-size: 200%;
}
div.refnamediv
{
margin-top: 2em;
}
div.gallery-float
{
float: left;
padding: 10px;
}
div.gallery-float img
{
border-style: none;
}
div.gallery-spacer
{
clear: both;
}
a
{
text-decoration: none;
}
a:hover
{
text-decoration: underline;
color: #FF0000;
}
"""
class DocumentationItem:
"""
A class to hold information about a configuration
item. It contains the key name, description, a list of related names,
and the group this item is contained in.
"""
def __init__(self):
self._groups = []
self._related = []
self._name = ""
self._desc = ""
def groups(self):
return self._groups
def name(self):
return self._name
def description(self):
return self._desc
def related(self):
return self._related
def setName(self, name):
self._name = name
def setDescription(self, desc):
self._desc = desc
def addGroup(self, group):
self._groups.append(group)
def addRelation(self,relation):
self._related.append(relation)
def sort(self):
self._related.sort()
self._groups.sort()
class Documentation:
"""
Holds the documentation... with mappings from key to items...
"""
def __init__(self):
self.__keys = {}
self.__groups = {}
def insert_doc_item(self, item):
"""
Insert the Doc Item into the internal list
of representation
"""
item.sort()
self.__keys[item.name()] = item
for group in item.groups():
if not group in self.__groups:
self.__groups[group] = []
self.__groups[group].append(item)
self.__groups[group].sort()
def doc_item(self, key):
"""
Return the DocumentationInstance describing the key
"""
try:
return self.__keys[key]
except KeyError:
return None
def doc_keys(self):
"""
Return the documented KEYS (names)
"""
return self.__keys.keys()
def groups(self):
"""
Return the names of available groups
"""
return self.__groups.keys()
def group_content(self,group_name):
"""
Return a list of keys/names that are in a specefic
group or the empty list
"""
try:
return self.__groups[group_name]
except KeyError:
return []
def parse_cmdline(args):
"""
Parse the CMD line and return the result as a n-tuple
"""
parser = optparse.OptionParser( version = "Bitbake Documentation Tool Core version %s, %%prog version %s" % (bb.__version__,__version__))
usage = """%prog [options]
Create a set of html pages (documentation) for a bitbake.conf....
"""
# Add the needed options
parser.add_option( "-c", "--config", help = "Use the specified configuration file as source",
action = "store", dest = "config", default = os.path.join("conf", "documentation.conf") )
parser.add_option( "-o", "--output", help = "Output directory for html files",
action = "store", dest = "output", default = "html/" )
parser.add_option( "-D", "--debug", help = "Increase the debug level",
action = "count", dest = "debug", default = 0 )
parser.add_option( "-v","--verbose", help = "output more chit-char to the terminal",
action = "store_true", dest = "verbose", default = False )
options, args = parser.parse_args( sys.argv )
if options.debug:
bb.debug_level = options.debug
return options.config, options.output
def main():
"""
The main Method
"""
(config_file,output_dir) = parse_cmdline( sys.argv )
# right to let us load the file now
try:
documentation = bb.parse.handle( config_file, bb.data.init() )
except IOError:
bb.fatal( "Unable to open %s" % config_file )
except bb.parse.ParseError:
bb.fatal( "Unable to parse %s" % config_file )
# Assuming we've the file loaded now, we will initialize the 'tree'
doc = Documentation()
# defined states
state_begin = 0
state_see = 1
state_group = 2
for key in bb.data.keys(documentation):
data = bb.data.getVarFlag(key, "doc", documentation)
if not data:
continue
# The Documentation now starts
doc_ins = DocumentationItem()
doc_ins.setName(key)
tokens = data.split(' ')
state = state_begin
string= ""
for token in tokens:
token = token.strip(',')
if not state == state_see and token == "@see":
state = state_see
continue
elif not state == state_group and token == "@group":
state = state_group
continue
if state == state_begin:
string += " %s" % token
elif state == state_see:
doc_ins.addRelation(token)
elif state == state_group:
doc_ins.addGroup(token)
# set the description
doc_ins.setDescription(string)
doc.insert_doc_item(doc_ins)
# let us create the HTML now
bb.mkdirhier(output_dir)
os.chdir(output_dir)
# Let us create the sites now. We do it in the following order
# Start with the index.html. It will point to sites explaining all
# keys and groups
html_slave = HTMLFormatter()
f = file('style.css', 'w')
print >> f, html_slave.createCSS()
f = file('index.html', 'w')
print >> f, html_slave.createIndex()
f = file('groups.html', 'w')
print >> f, html_slave.createGroupsSite(doc)
f = file('keys.html', 'w')
print >> f, html_slave.createKeysSite(doc)
# now for each group create the site
for group in doc.groups():
f = file('group%s.html' % group, 'w')
print >> f, html_slave.createGroupSite(group, doc.group_content(group))
# now for the keys
for key in doc.doc_keys():
f = file('key%s.html' % doc.doc_item(key).name(), 'w')
print >> f, html_slave.createKeySite(doc.doc_item(key))
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,79 @@
# Copyright (C) 2003 Chris Larson
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
die() {
bbfatal "$*"
}
bbnote() {
echo "NOTE:" "$*"
}
bbwarn() {
echo "WARNING:" "$*"
}
bbfatal() {
echo "FATAL:" "$*"
exit 1
}
bbdebug() {
test $# -ge 2 || {
echo "Usage: bbdebug level \"message\""
exit 1
}
test ${@bb.debug_level} -ge $1 && {
shift
echo "DEBUG:" $*
}
}
addtask showdata
do_showdata[nostamp] = "1"
python do_showdata() {
import sys
# emit variables and shell functions
bb.data.emit_env(sys.__stdout__, d, True)
# emit the metadata which isnt valid shell
for e in bb.data.keys(d):
if bb.data.getVarFlag(e, 'python', d):
sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1)))
}
addtask listtasks
do_listtasks[nostamp] = "1"
python do_listtasks() {
import sys
for e in bb.data.keys(d):
if bb.data.getVarFlag(e, 'task', d):
sys.__stdout__.write("%s\n" % e)
}
addtask build
do_build[dirs] = "${TOPDIR}"
do_build[nostamp] = "1"
python base_do_build () {
bb.note("The included, default BB base.bbclass does not define a useful default task.")
bb.note("Try running the 'listtasks' task against a .bb to see what tasks are defined.")
}
EXPORT_FUNCTIONS do_clean do_mrproper do_build

55
bitbake/conf/bitbake.conf Normal file
View File

@@ -0,0 +1,55 @@
# Copyright (C) 2003 Chris Larson
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
B = "${S}"
CVSDIR = "${DL_DIR}/cvs"
DEPENDS = ""
DEPLOY_DIR = "${TMPDIR}/deploy"
DEPLOY_DIR_IMAGE = "${DEPLOY_DIR}/images"
DL_DIR = "${TMPDIR}/downloads"
FETCHCOMMAND = ""
FETCHCOMMAND_cvs = "/usr/bin/env cvs -d${CVSROOT} co ${CVSCOOPTS} ${CVSMODULE}"
FETCHCOMMAND_svn = "/usr/bin/env svn co http://${SVNROOT} ${SVNCOOPTS} ${SVNMODULE}"
FETCHCOMMAND_wget = "/usr/bin/env wget -t 5 --passive-ftp -P ${DL_DIR} ${URI}"
FILESDIR = "${@bb.which(bb.data.getVar('FILESPATH', d, 1), '.')}"
FILESPATH = "${FILE_DIRNAME}/${PF}:${FILE_DIRNAME}/${P}:${FILE_DIRNAME}/${PN}:${FILE_DIRNAME}/files:${FILE_DIRNAME}"
FILE_DIRNAME = "${@os.path.dirname(bb.data.getVar('FILE', d))}"
IMAGE_CMD = "_NO_DEFINED_IMAGE_TYPES_"
IMAGE_ROOTFS = "${TMPDIR}/rootfs"
MKTEMPCMD = "mktemp -q ${TMPBASE}"
MKTEMPDIRCMD = "mktemp -d -q ${TMPBASE}"
OVERRIDES = "local:${MACHINE}:${TARGET_OS}:${TARGET_ARCH}"
P = "${PN}-${PV}"
PF = "${PN}-${PV}-${PR}"
PN = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[0] or 'defaultpkgname'}"
PR = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[2] or 'r0'}"
PROVIDES = ""
PV = "${@bb.parse.BBHandler.vars_from_file(bb.data.getVar('FILE',d),d)[1] or '1.0'}"
RESUMECOMMAND = ""
RESUMECOMMAND_wget = "/usr/bin/env wget -c -t 5 --passive-ftp -P ${DL_DIR} ${URI}"
S = "${WORKDIR}/${P}"
SRC_URI = "file://${FILE}"
STAMP = "${TMPDIR}/stamps/${PF}"
T = "${WORKDIR}/temp"
TARGET_ARCH = "${BUILD_ARCH}"
TMPDIR = "${TOPDIR}/tmp"
UPDATECOMMAND = ""
UPDATECOMMAND_cvs = "/usr/bin/env cvs update ${CVSCOOPTS}"
WORKDIR = "${TMPDIR}/work/${PF}"

1
bitbake/contrib/README Normal file
View File

@@ -0,0 +1 @@
This directory is for additional contributed files which may be useful.

31
bitbake/contrib/bbdev.sh Normal file
View File

@@ -0,0 +1,31 @@
# This is a shell function to be sourced into your shell or placed in your .profile,
# which makes setting things up for BitBake a bit easier.
#
# The author disclaims copyright to the contents of this file and places it in the
# public domain.
bbdev () {
local BBDIR PKGDIR BUILDDIR
if test x"$1" = "x--help"; then echo >&2 "syntax: bbdev [bbdir [pkgdir [builddir]]]"; return 1; fi
if test x"$1" = x; then BBDIR=`pwd`; else BBDIR=$1; fi
if test x"$2" = x; then PKGDIR=`pwd`; else PKGDIR=$2; fi
if test x"$3" = x; then BUILDDIR=`pwd`; else BUILDDIR=$3; fi
BBDIR=`readlink -f $BBDIR`
PKGDIR=`readlink -f $PKGDIR`
BUILDDIR=`readlink -f $BUILDDIR`
if ! (test -d $BBDIR && test -d $PKGDIR && test -d $BUILDDIR); then
echo >&2 "syntax: bbdev [bbdir [pkgdir [builddir]]]"
return 1
fi
PATH=$BBDIR/bin:$PATH
BBPATH=$BBDIR
if test x"$BBDIR" != x"$PKGDIR"; then
BBPATH=$PKGDIR:$BBPATH
fi
if test x"$PKGDIR" != x"$BUILDDIR"; then
BBPATH=$BUILDDIR:$BBPATH
fi
export BBPATH
}

340
bitbake/doc/COPYING.GPL Normal file
View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

17
bitbake/doc/COPYING.MIT Normal file
View File

@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,56 @@
topdir = .
manual = $(topdir)/usermanual.xml
# types = pdf txt rtf ps xhtml html man tex texi dvi
# types = pdf txt
types = $(xmltotypes) $(htmltypes)
xmltotypes = pdf txt
htmltypes = html xhtml
htmlxsl = $(if $(filter $@,$(foreach type,$(htmltypes),$(type)-nochunks)),http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl,http://docbook.sourceforge.net/release/xsl/current/$@/chunk.xsl)
htmlcssfile = docbook.css
htmlcss = $(topdir)/html.css
# htmlcssfile =
# htmlcss =
cleanfiles = $(foreach i,$(types),$(topdir)/$(i))
ifdef DEBUG
define command
$(1)
endef
else
define command
@echo $(2) $(3) $(4)
@$(1) >/dev/null
endef
endif
all: $(types)
lint: $(manual) FORCE
$(call command,xmllint --xinclude --postvalid --noout $(manual),XMLLINT $(manual))
$(types) $(foreach type,$(htmltypes),$(type)-nochunks): lint FORCE
$(foreach type,$(htmltypes),$(type)-nochunks): $(if $(htmlcss),$(htmlcss)) $(manual)
@mkdir -p $@
ifdef htmlcss
$(call command,install -m 0644 $(htmlcss) $@/$(htmlcssfile),CP $(htmlcss) $@/$(htmlcssfile))
endif
$(call command,xsltproc --stringparam base.dir $@/ $(if $(htmlcssfile),--stringparam html.stylesheet $(htmlcssfile)) $(htmlxsl) $(manual) > $@/index.$(patsubst %-nochunks,%,$@),XSLTPROC $@ $(manual))
$(htmltypes): $(if $(htmlcss),$(htmlcss)) $(manual)
@mkdir -p $@
ifdef htmlcss
$(call command,install -m 0644 $(htmlcss) $@/$(htmlcssfile),CP $(htmlcss) $@/$(htmlcssfile))
endif
$(call command,xsltproc --stringparam base.dir $@/ $(if $(htmlcssfile),--stringparam html.stylesheet $(htmlcssfile)) $(htmlxsl) $(manual),XSLTPROC $@ $(manual))
$(xmltotypes): $(manual)
$(call command,xmlto --extensions -o $(topdir)/$@ $@ $(manual),XMLTO $@ $(manual))
clean:
rm -rf $(cleanfiles)
$(foreach i,$(types) $(foreach type,$(htmltypes),$(type)-nochunks),clean-$(i)):
rm -rf $(patsubst clean-%,%,$@)
FORCE:

281
bitbake/doc/manual/html.css Normal file
View File

@@ -0,0 +1,281 @@
/* Feuille de style DocBook du projet Traduc.org */
/* DocBook CSS stylesheet of the Traduc.org project */
/* (c) Jean-Philippe Gu<47>rard - 14 ao<61>t 2004 */
/* (c) Jean-Philippe Gu<47>rard - 14 August 2004 */
/* Cette feuille de style est libre, vous pouvez la */
/* redistribuer et la modifier selon les termes de la Licence */
/* Art Libre. Vous trouverez un exemplaire de cette Licence sur */
/* http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
/* This work of art is free, you can redistribute it and/or */
/* modify it according to terms of the Free Art license. You */
/* will find a specimen of this license on the Copyleft */
/* Attitude web site: http://artlibre.org as well as on other */
/* sites. */
/* Please note that the French version of this licence as shown */
/* on http://tigreraye.org/Petit-guide-du-traducteur.html#licence-art-libre */
/* is only official licence of this document. The English */
/* is only provided to help you understand this licence. */
/* La derni<6E>re version de cette feuille de style est toujours */
/* disponible sur<75>: http://tigreraye.org/style.css */
/* Elle est <20>galement disponible sur<75>: */
/* http://www.traduc.org/docs/HOWTO/lecture/style.css */
/* The latest version of this stylesheet is available from: */
/* http://tigreraye.org/style.css */
/* It is also available on: */
/* http://www.traduc.org/docs/HOWTO/lecture/style.css */
/* N'h<>sitez pas <20> envoyer vos commentaires et corrections <20> */
/* Jean-Philippe Gu<47>rard <jean-philippe.guerard@tigreraye.org> */
/* Please send feedback and bug reports to */
/* Jean-Philippe Gu<47>rard <jean-philippe.guerard@tigreraye.org> */
/* $Id: style.css,v 1.14 2004/09/10 20:12:09 fevrier Exp fevrier $ */
/* Pr<50>sentation g<>n<EFBFBD>rale du document */
/* Overall document presentation */
body {
/*
font-family: Apolline, "URW Palladio L", Garamond, jGaramond,
"Bitstream Cyberbit", "Palatino Linotype", serif;
*/
margin: 7%;
background-color: white;
}
/* Taille du texte */
/* Text size */
* { font-size: 100%; }
/* Gestion des textes mis en relief imbriqu<71>s */
/* Embedded emphasis */
em { font-style: italic; }
em em { font-style: normal; }
em em em { font-style: italic; }
/* Titres */
/* Titles */
h1 { font-size: 200%; font-weight: 900; }
h2 { font-size: 160%; font-weight: 900; }
h3 { font-size: 130%; font-weight: bold; }
h4 { font-size: 115%; font-weight: bold; }
h5 { font-size: 108%; font-weight: bold; }
h6 { font-weight: bold; }
/* Nom de famille en petites majuscules (uniquement en fran<61>ais) */
/* Last names in small caps (for French only) */
*[class~="surname"]:lang(fr) { font-variant: small-caps; }
/* Blocs de citation */
/* Quotation blocs */
div[class~="blockquote"] {
border: solid 2px #AAA;
padding: 5px;
margin: 5px;
}
div[class~="blockquote"] > table {
border: none;
}
/* Blocs lit<69>raux<75>: fond gris clair */
/* Literal blocs: light gray background */
*[class~="literallayout"] {
background: #f0f0f0;
padding: 5px;
margin: 5px;
}
/* Programmes et captures texte<74>: fond bleu clair */
/* Listing and text screen snapshots: light blue background */
*[class~="programlisting"], *[class~="screen"] {
background: #f0f0ff;
padding: 5px;
margin: 5px;
}
/* Les textes <20> remplacer sont surlign<67>s en vert p<>le */
/* Replaceable text in highlighted in pale green */
*[class~="replaceable"] {
background-color: #98fb98;
font-style: normal; }
/* Tables<65>: fonds gris clair & bords simples */
/* Tables: light gray background and solid borders */
*[class~="table"] *[class~="title"] { width:100%; border: 0px; }
table {
border: 1px solid #aaa;
border-collapse: collapse;
padding: 2px;
margin: 5px;
}
/* Listes simples en style table */
/* Simples lists in table presentation */
table[class~="simplelist"] {
background-color: #F0F0F0;
margin: 5px;
border: solid 1px #AAA;
}
table[class~="simplelist"] td {
border: solid 1px #AAA;
}
/* Les tables */
/* Tables */
*[class~="table"] table {
background-color: #F0F0F0;
border: solid 1px #AAA;
}
*[class~="informaltable"] table { background-color: #F0F0F0; }
th,td {
vertical-align: baseline;
text-align: left;
padding: 0.1em 0.3em;
empty-cells: show;
}
/* Alignement des colonnes */
/* Colunms alignment */
td[align=center] , th[align=center] { text-align: center; }
td[align=right] , th[align=right] { text-align: right; }
td[align=left] , th[align=left] { text-align: left; }
td[align=justify] , th[align=justify] { text-align: justify; }
/* Pas de marge autour des images */
/* No inside margins for images */
img { border: 0; }
/* Les liens ne sont pas soulign<67>s */
/* No underlines for links */
:link , :visited , :active { text-decoration: none; }
/* Prudence<63>: cadre jaune et fond jaune clair */
/* Caution: yellow border and light yellow background */
*[class~="caution"] {
border: solid 2px yellow;
background-color: #ffffe0;
padding: 1em 6px 1em ;
margin: 5px;
}
*[class~="caution"] th {
vertical-align: middle
}
*[class~="caution"] table {
background-color: #ffffe0;
border: none;
}
/* Note importante<74>: cadre jaune et fond jaune clair */
/* Important: yellow border and light yellow background */
*[class~="important"] {
border: solid 2px yellow;
background-color: #ffffe0;
padding: 1em 6px 1em;
margin: 5px;
}
*[class~="important"] th {
vertical-align: middle
}
*[class~="important"] table {
background-color: #ffffe0;
border: none;
}
/* Mise en <20>vidence<63>: texte l<>g<EFBFBD>rement plus grand */
/* Highlights: slightly larger texts */
*[class~="highlights"] {
font-size: 110%;
}
/* Note<74>: cadre bleu et fond bleu clair */
/* Notes: blue border and light blue background */
*[class~="note"] {
border: solid 2px #7099C5;
background-color: #f0f0ff;
padding: 1em 6px 1em ;
margin: 5px;
}
*[class~="note"] th {
vertical-align: middle
}
*[class~="note"] table {
background-color: #f0f0ff;
border: none;
}
/* Astuce<63>: cadre vert et fond vert clair */
/* Tip: green border and light green background */
*[class~="tip"] {
border: solid 2px #00ff00;
background-color: #f0ffff;
padding: 1em 6px 1em ;
margin: 5px;
}
*[class~="tip"] th {
vertical-align: middle;
}
*[class~="tip"] table {
background-color: #f0ffff;
border: none;
}
/* Avertissement<6E>: cadre rouge et fond rouge clair */
/* Warning: red border and light red background */
*[class~="warning"] {
border: solid 2px #ff0000;
background-color: #fff0f0;
padding: 1em 6px 1em ;
margin: 5px;
}
*[class~="warning"] th {
vertical-align: middle;
}
*[class~="warning"] table {
background-color: #fff0f0;
border: none;
}
/* Fin */
/* The End */

View File

@@ -0,0 +1,361 @@
<?xml version="1.0"?>
<!--
ex:ts=4:sw=4:sts=4:et
-*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-->
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<book>
<bookinfo>
<title>BitBake User Manual</title>
<authorgroup>
<corpauthor>BitBake Team</corpauthor>
</authorgroup>
<copyright>
<year>2004, 2005</year>
<holder>Chris Larson</holder>
<holder>Phil Blundell</holder>
</copyright>
<legalnotice>
<para>This work is licensed under the Creative Commons Attribution License. To view a copy of this license, visit <ulink url="http://creativecommons.org/licenses/by/2.0/">http://creativecommons.org/licenses/by/2.0/</ulink> or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.</para>
</legalnotice>
</bookinfo>
<chapter>
<title>Introduction</title>
<section>
<title>Overview</title>
<para>BitBake is, at its simplest, a tool for executing
tasks and managing metadata. As such, its similarities to GNU make and other
build tools are readily apparent. It was inspired by Portage, the package management system used by the Gentoo Linux distribution. BitBake is the basis of the <ulink url="http://www.openembedded.org/">OpenEmbedded</ulink> project, which is being used to build and maintain a number of embedded Linux distributions, including OpenZaurus and Familiar.</para>
</section>
<section>
<title>Background and Goals</title>
<para>Prior to BitBake, no other build tool adequately met
the needs of an aspiring embedded Linux distribution. All of the
buildsystems used by traditional desktop Linux distributions lacked
important functionality, and none of the ad-hoc
<emphasis>buildroot</emphasis> systems, prevalent in the
embedded space, were scalable or maintainable.</para>
<para>Some important goals for BitBake were:
<itemizedlist>
<listitem><para>Handle crosscompilation.</para></listitem>
<listitem><para>Handle interpackage dependencies (build time on target architecture, build time on native architecture, and runtime).</para></listitem>
<listitem><para>Support running any number of tasks within a given package, including, but not limited to, fetching upstream sources, unpacking them, patching them, configuring them, et cetera.</para></listitem>
<listitem><para>Must be linux distribution agnostic (both build and target).</para></listitem>
<listitem><para>Must be architecture agnostic</para></listitem>
<listitem><para>Must support multiple build and target operating systems (including cygwin, the BSDs, etc).</para></listitem>
<listitem><para>Must be able to be self contained, rather than tightly integrated into the build machine's root filesystem.</para></listitem>
<listitem><para>There must be a way to handle conditional metadata (on target architecture, operating system, distribution, machine).</para></listitem>
<listitem><para>It must be easy for the person using the tools to supply their own local metadata and packages to operate against.</para></listitem>
<listitem><para>Must make it easy to collaborate
between multiple projects using BitBake for their
builds.</para></listitem>
<listitem><para>Should provide an inheritance mechanism to
share common metadata between many packages.</para></listitem>
<listitem><para>Et cetera...</para></listitem>
</itemizedlist>
</para>
<para>BitBake satisfies all these and many more. Flexibility and power have always been the priorities. It is highly extensible, supporting embedded Python code and execution of any arbitrary tasks.</para>
</section>
</chapter>
<chapter>
<title>Metadata</title>
<section>
<title>Description</title>
<itemizedlist>
<para>BitBake metadata can be classified into 3 major areas:</para>
<listitem>
<para>Configuration Files</para>
</listitem>
<listitem>
<para>.bb Files</para>
</listitem>
<listitem>
<para>Classes</para>
</listitem>
</itemizedlist>
<para>What follows are a large number of examples of BitBake metadata. Any syntax which isn't supported in any of the aforementioned areas will be documented as such.</para>
<section>
<title>Basic variable setting</title>
<para><screen><varname>VARIABLE</varname> = "value"</screen></para>
<para>In this example, <varname>VARIABLE</varname> is <literal>value</literal>.</para>
</section>
<section>
<title>Variable expansion</title>
<para>BitBake supports variables referencing one another's contents using a syntax which is similar to shell scripting</para>
<para><screen><varname>A</varname> = "aval"
<varname>B</varname> = "pre${A}post"</screen></para>
<para>This results in <varname>A</varname> containing <literal>aval</literal> and <varname>B</varname> containing <literal>preavalpost</literal>.</para>
</section>
<section>
<title>Immediate variable expansion (:=)</title>
<para>:= results in a variable's contents being expanded immediately, rather than when the variable is actually used.</para>
<para><screen><varname>T</varname> = "123"
<varname>A</varname> := "${B} ${A} test ${T}"
<varname>T</varname> = "456"
<varname>B</varname> = "${T} bval"
<varname>C</varname> = "cval"
<varname>C</varname> := "${C}append"</screen></para>
<para>In that example, <varname>A</varname> would contain <literal> test 123</literal>, <varname>B</varname> would contain <literal>456 bval</literal>, and <varname>C</varname> would be <literal>cvalappend</literal>.</para>
</section>
<section>
<title>Appending (+=) and prepending (=+)</title>
<para><screen><varname>B</varname> = "bval"
<varname>B</varname> += "additionaldata"
<varname>C</varname> = "cval"
<varname>C</varname> =+ "test"</screen></para>
<para>In this example, <varname>B</varname> is now <literal>bval additionaldata</literal> and <varname>C</varname> is <literal>test cval</literal>.</para>
</section>
<section>
<title>Appending (.=) and prepending (=.) without spaces</title>
<para><screen><varname>B</varname> = "bval"
<varname>B</varname> += "additionaldata"
<varname>C</varname> = "cval"
<varname>C</varname> =+ "test"</screen></para>
<para>In this example, <varname>B</varname> is now <literal>bvaladditionaldata</literal> and <varname>C</varname> is <literal>testcval</literal>. In contrast to the above Appending and Prepending operators no additional space
will be introduced.</para>
</section>
<section>
<title>Conditional metadata set</title>
<para>OVERRIDES is a <quote>:</quote> seperated variable containing each item you want to satisfy conditions. So, if you have a variable which is conditional on <quote>arm</quote>, and <quote>arm</quote> is in OVERRIDES, then the <quote>arm</quote> specific version of the variable is used rather than the non-conditional version. Example:</para>
<para><screen><varname>OVERRIDES</varname> = "architecture:os:machine"
<varname>TEST</varname> = "defaultvalue"
<varname>TEST_os</varname> = "osspecificvalue"
<varname>TEST_condnotinoverrides</varname> = "othercondvalue"</screen></para>
<para>In this example, <varname>TEST</varname> would be <literal>osspecificvalue</literal>, due to the condition <quote>os</quote> being in <varname>OVERRIDES</varname>.</para>
</section>
<section>
<title>Conditional appending</title>
<para>BitBake also supports appending and prepending to variables based on whether something is in OVERRIDES. Example:</para>
<para><screen><varname>DEPENDS</varname> = "glibc ncurses"
<varname>OVERRIDES</varname> = "machine:local"
<varname>DEPENDS_append_machine</varname> = " libmad"</screen></para>
<para>In this example, <varname>DEPENDS</varname> is set to <literal>glibc ncurses libmad</literal>.</para>
</section>
<section>
<title>Inclusion</title>
<para>Next, there is the <literal>include</literal> directive, which causes BitBake to parse in whatever file you specify, and insert it at that location, which is not unlike <command>make</command>. However, if the path specified on the <literal>include</literal> line is a relative path, BitBake will locate the first one it can find within <envar>BBPATH</envar>.</para>
</section>
<section>
<title>Python variable expansion</title>
<para><screen><varname>DATE</varname> = "${@time.strftime('%Y%m%d',time.gmtime())}"</screen></para>
<para>This would result in the <varname>DATE</varname> variable containing today's date.</para>
</section>
<section>
<title>Defining executable metadata</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para><screen>do_mytask () {
echo "Hello, world!"
}</screen></para>
<para>This is essentially identical to setting a variable, except that this variable happens to be executable shell code.</para>
<para><screen>python do_printdate () {
import time
print time.strftime('%Y%m%d', time.gmtime())
}</screen></para>
<para>This is the similar to the previous, but flags it as python so that BitBake knows it is python code.</para>
</section>
<section>
<title>Defining python functions into the global python namespace</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para><screen>def get_depends(bb, d):
if bb.data.getVar('SOMECONDITION', d, True):
return "dependencywithcond"
else:
return "dependency"
<varname>SOMECONDITION</varname> = "1"
<varname>DEPENDS</varname> = "${@get_depends(bb, d)}"</screen></para>
<para>This would result in <varname>DEPENDS</varname> containing <literal>dependencywithcond</literal>.</para>
</section>
<section>
<title>Inheritance</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para>The <literal>inherit</literal> directive is a means of specifying what classes of functionality your .bb requires. It is a rudamentary form of inheritence. For example, you can easily abstract out the tasks involved in building a package that uses autoconf and automake, and put that into a bbclass for your packages to make use of. A given bbclass is located by searching for classes/filename.oeclass in <envar>BBPATH</envar>, where filename is what you inherited.</para>
</section>
<section>
<title>Tasks</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para>In BitBake, each step that needs to be run for a given .bb is known as a task. There is a command <literal>addtask</literal> to add new tasks (must be a defined python executable metadata and must start with <quote>do_</quote>) and describe intertask dependencies.</para>
<para><screen>python do_printdate () {
import time
print time.strftime('%Y%m%d', time.gmtime())
}
addtask printdate before do_build</screen></para>
<para>This defines the necessary python function and adds it as a task which is now a dependency of do_build (the default task). If anyone executes the do_build task, that will result in do_printdate being run first.</para>
</section>
<section>
<title>Events</title>
<para><emphasis>NOTE:</emphasis> This is only supported in .bb and .bbclass files.</para>
<para>BitBake also implements a means of registering event handlers. Events are triggered at certain points during operation, such as, the beginning of operation against a given .bb, the start of a given task, task failure, task success, et cetera. The intent was to make it easy to do things like email notifications on build failure.</para>
<para><screen>addhandler myclass_eventhandler
python myclass_eventhandler() {
from bb.event import NotHandled, getName
from bb import data
print "The name of the Event is %s" % getName(e)
print "The file we run for is %s" % data.getVar('FILE', e.data, True)
return NotHandled
</screen></para><para>
This event handler gets called every time an event is triggered. A global variable <varname>e</varname> is defined. <varname>e</varname>.data contains an instance of bb.data. With the getName(<varname>e</varname>)
method one can get the name of the triggered event.</para><para>The above event handler prints the name
of the event and the content of the <varname>FILE</varname> variable.</para>
</section>
</section>
<section>
<title>Parsing</title>
<section>
<title>Configuration Files</title>
<para>The first of the classifications of metadata in BitBake is configuration metadata. This metadata is global, and therefore affects <emphasis>all</emphasis> packages and tasks which are executed. Currently, BitBake has hardcoded knowledge of a single configuration file. It expects to find 'conf/bitbake.conf' somewhere in the user specified <envar>BBPATH</envar>. That configuration file generally has include directives to pull in any other metadata (generally files specific to architecture, machine, <emphasis>local</emphasis> and so on.</para>
<para>Only variable definitions and include directives are allowed in .conf files.</para>
</section>
<section>
<title>Classes</title>
<para>BitBake classes are our rudamentary inheritence mechanism. As briefly mentioned in the metadata introduction, they're parsed when an <literal>inherit</literal> directive is encountered, and they are located in classes/ relative to the dirs in <envar>BBPATH</envar>.</para>
</section>
<section>
<title>.bb Files</title>
<para>A BitBake (.bb) file is a logical unit of tasks to be executed. Normally this is a package to be built. Inter-.bb dependencies are obeyed. The files themselves are located via the <varname>BBFILES</varname> variable, which is set to a space seperated list of .bb files, and does handle wildcards.</para>
</section>
</section>
</chapter>
<chapter>
<title>Commands</title>
<section>
<title>bbread</title>
<para>bbread is a command for displaying BitBake metadata. When run with no arguments, it has the core parse 'conf/bitbake.conf', as located in BBPATH, and displays that. If you supply a file on the commandline, such as a .bb, then it parses that afterwards, using the aforementioned configuration metadata.</para>
<para><emphasis>NOTE: the stand a lone bbread command was removed. Instead of bbread use bitbake -e.
</emphasis></para>
</section>
<section>
<title>bitbake</title>
<section>
<title>Introduction</title>
<para>bitbake is the primary command in the system. It facilitates executing tasks in a single .bb file, or executing a given task on a set of multiple .bb files, accounting for interdependencies amongst them.</para>
</section>
<section>
<title>Usage and Syntax</title>
<para>
<screen><prompt>$ </prompt>bitbake --help
usage: bitbake [options] [package ...]
Executes the specified task (default is 'build') for a given set of BitBake files.
It expects that BBFILES is defined, which is a space seperated list of files to
be executed. BBFILES does support wildcards.
Default BBFILES are the .bb files in the current directory.
options:
--version show program's version number and exit
-h, --help show this help message and exit
-b BUILDFILE, --buildfile=BUILDFILE
execute the task against this .bb file, rather than a
package from BBFILES.
-k, --continue continue as much as possible after an error. While the
target that failed, and those that depend on it,
cannot be remade, the other dependencies of these
targets can be processed all the same.
-f, --force force run of specified cmd, regardless of stamp status
-i, --interactive drop into the interactive mode.
-c CMD, --cmd=CMD Specify task to execute. Note that this only executes
the specified task for the providee and the packages
it depends on, i.e. 'compile' does not implicitly call
stage for the dependencies (IOW: use only if you know
what you are doing)
-r FILE, --read=FILE read the specified file before bitbake.conf
-v, --verbose output more chit-chat to the terminal
-D, --debug Increase the debug level
-n, --dry-run don't execute, just go through the motions
-p, --parse-only quit after parsing the BB files (developers only)
-d, --disable-psyco disable using the psyco just-in-time compiler (not
recommended)
-s, --show-versions show current and preferred versions of all packages
-e, --environment show the global or per-package environment (this is
what used to be bbread)
</screen>
</para>
<para>
<example>
<title>Executing a task against a single .bb</title>
<para>Executing tasks for a single file is relatively simple. You specify the file in question, and bitbake parses it and executes the specified task (or <quote>build</quote> by default). It obeys intertask dependencies when doing so.</para>
<para><quote>clean</quote> task:</para>
<para><screen><prompt>$ </prompt>bitbake -b blah_1.0.bb -c clean</screen></para>
<para><quote>build</quote> task:</para>
<para><screen><prompt>$ </prompt>bitbake -b blah_1.0.bb</screen></para>
</example>
</para>
<para>
<example>
<title>Executing tasks against a set of .bb files</title>
<para>There are a number of additional complexities introduced when one wants to manage multiple .bb files. Clearly there needs to be a way to tell bitbake what files are available, and of those, which we want to execute at this time. There also needs to be a way for each .bb to express its dependencies, both for build time and runtime. There must be a way for the user to express their preferences when multiple .bb's provide the same functionality, or when there are multiple versions of a .bb.</para>
<para>The next section, Metadata, outlines how one goes about specifying such things.</para>
<para>Note that the bitbake command, when not using --buildfile, accepts a <varname>PROVIDER</varname>, not a filename or anything else. By default, a .bb generally PROVIDES its packagename, packagename-version, and packagename-version-revision.</para>
<screen><prompt>$ </prompt>bitbake blah</screen>
<screen><prompt>$ </prompt>bitbake blah-1.0</screen>
<screen><prompt>$ </prompt>bitbake blah-1.0-r0</screen>
<screen><prompt>$ </prompt>bitbake -c clean blah</screen>
<screen><prompt>$ </prompt>bitbake virtual/whatever</screen>
<screen><prompt>$ </prompt>bitbake -c clean virtual/whatever</screen>
</example>
</para>
</section>
<section>
<title>Metadata</title>
<para>As you may have seen in the usage information, or in the information about .bb files, the BBFILES variable is how the bitbake tool locates its files. This variable is a space seperated list of files that are available, and supports wildcards.
<example>
<title>Setting BBFILES</title>
<programlisting><varname>BBFILES</varname> = "/path/to/bbfiles/*.bb"</programlisting>
</example></para>
<para>With regard to dependencies, it expects the .bb to define a <varname>DEPENDS</varname> variable, which contains a space seperated list of <quote>package names</quote>, which themselves are the <varname>PN</varname> variable. The <varname>PN</varname> variable is, in general, by default, set to a component of the .bb filename.</para>
<example>
<title>Depending on another .bb</title>
<para>a.bb:
<screen>PN = "package-a"
DEPENDS += "package-b"</screen>
</para>
<para>b.bb:
<screen>PN = "package-b"</screen>
</para>
</example>
<example>
<title>Using PROVIDES</title>
<para>This example shows the usage of the PROVIDES variable, which allows a given .bb to specify what functionality it provides.</para>
<para>package1.bb:
<screen>PROVIDES += "virtual/package"</screen>
</para>
<para>package2.bb:
<screen>DEPENDS += "virtual/package"</screen>
</para>
<para>package3.bb:
<screen>PROVIDES += "virtual/package"</screen>
</para>
<para>As you can see, here there are two different .bb's that provide the same functionality (virtual/package). Clearly, there needs to be a way for the person running bitbake to control which of those providers gets used. There is, indeed, such a way.</para>
<para>The following would go into a .conf file, to select package1:
<screen>PREFERRED_PROVIDER_virtual/package = "package1"</screen>
</para>
</example>
<example>
<title>Specifying version preference</title>
<para>When there are multiple <quote>versions</quote> of a given package, bitbake defaults to selecting the most recent version, unless otherwise specified. If the .bb in question has a <varname>DEFAULT_PREFERENCE</varname> set lower than the other .bb's (default is 0), then it will not be selected. This allows the person or persons maintaining the repository of .bb files to specify their preferences for the default selected version. In addition, the user can specify their preferences with regard to version.</para>
<para>If the first .bb is named <filename>a_1.1.bb</filename>, then the <varname>PN</varname> variable will be set to <quote>a</quote>, and the <varname>PV</varname> variable will be set to 1.1.</para>
<para>If we then have an <filename>a_1.2.bb</filename>, bitbake will choose 1.2 by default. However, if we define the following variable in a .conf that bitbake parses, we can change that.
<screen>PREFERRED_VERSION_a = "1.1"</screen>
</para>
</example>
<example>
<title>Using <quote>bbfile collections</quote></title>
<para>bbfile collections exist to allow the user to have multiple repositories of bbfiles that contain the same exact package. For example, one could easily use them to make one's own local copy of an upstream repository, but with custom modifications that one does not want upstream. Usage:</para>
<screen>BBFILES = "/stuff/openembedded/*/*.bb /stuff/openembedded.modified/*/*.bb"
BBFILE_COLLECTIONS = "upstream local"
BBFILE_PATTERN_upstream = "^/stuff/openembedded/"
BBFILE_PATTERN_local = "^/stuff/openembedded.modified/"
BBFILE_PRIORITY_upstream = "5"
BBFILE_PRIORITY_local = "10"</screen>
</example>
</section>
</section>
</chapter>
</book>

1266
bitbake/lib/bb/__init__.py Normal file

File diff suppressed because it is too large Load Diff

395
bitbake/lib/bb/build.py Normal file
View File

@@ -0,0 +1,395 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake 'Build' implementation
Core code for function execution and task handling in the
BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
Based on Gentoo's portage.py.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
from bb import debug, data, fetch, fatal, error, note, event, mkdirhier
import bb, os
# data holds flags and function name for a given task
_task_data = data.init()
# graph represents task interdependencies
_task_graph = bb.digraph()
# stack represents execution order, excepting dependencies
_task_stack = []
# events
class FuncFailed(Exception):
"""Executed function failed"""
class EventException(Exception):
"""Exception which is associated with an Event."""
def __init__(self, msg, event):
self.args = msg, event
class TaskBase(event.Event):
"""Base class for task events"""
def __init__(self, t, d ):
self._task = t
event.Event.__init__(self, d)
def getTask(self):
return self._task
def setTask(self, task):
self._task = task
task = property(getTask, setTask, None, "task property")
class TaskStarted(TaskBase):
"""Task execution started"""
class TaskSucceeded(TaskBase):
"""Task execution completed"""
class TaskFailed(TaskBase):
"""Task execution failed"""
class InvalidTask(TaskBase):
"""Invalid Task"""
# functions
def init(data):
global _task_data, _task_graph, _task_stack
_task_data = data.init()
_task_graph = bb.digraph()
_task_stack = []
def exec_func(func, d, dirs = None):
"""Execute an BB 'function'"""
body = data.getVar(func, d)
if not body:
return
if not dirs:
dirs = (data.getVarFlag(func, 'dirs', d) or "").split()
for adir in dirs:
adir = data.expand(adir, d)
mkdirhier(adir)
if len(dirs) > 0:
adir = dirs[-1]
else:
adir = data.getVar('B', d, 1)
adir = data.expand(adir, d)
try:
prevdir = os.getcwd()
except OSError:
prevdir = data.expand('${TOPDIR}', d)
if adir and os.access(adir, os.F_OK):
os.chdir(adir)
if data.getVarFlag(func, "python", d):
exec_func_python(func, d)
else:
exec_func_shell(func, d)
if os.path.exists(prevdir):
os.chdir(prevdir)
def exec_func_python(func, d):
"""Execute a python BB 'function'"""
import re, os
tmp = "def " + func + "():\n%s" % data.getVar(func, d)
comp = compile(tmp + '\n' + func + '()', bb.data.getVar('FILE', d, 1) + ':' + func, "exec")
prevdir = os.getcwd()
g = {} # globals
g['bb'] = bb
g['os'] = os
g['d'] = d
exec comp in g
if os.path.exists(prevdir):
os.chdir(prevdir)
def exec_func_shell(func, d):
"""Execute a shell BB 'function' Returns true if execution was successful.
For this, it creates a bash shell script in the tmp dectory, writes the local
data into it and finally executes. The output of the shell will end in a log file and stdout.
Note on directory behavior. The 'dirs' varflag should contain a list
of the directories you need created prior to execution. The last
item in the list is where we will chdir/cd to.
"""
import sys
deps = data.getVarFlag(func, 'deps', d)
check = data.getVarFlag(func, 'check', d)
if check in globals():
if globals()[check](func, deps):
return
global logfile
t = data.getVar('T', d, 1)
if not t:
return 0
mkdirhier(t)
logfile = "%s/log.%s.%s" % (t, func, str(os.getpid()))
runfile = "%s/run.%s.%s" % (t, func, str(os.getpid()))
f = open(runfile, "w")
f.write("#!/bin/sh -e\n")
if bb.debug_level > 0: f.write("set -x\n")
data.emit_env(f, d)
f.write("cd %s\n" % os.getcwd())
if func: f.write("%s\n" % func)
f.close()
os.chmod(runfile, 0775)
if not func:
error("Function not specified")
raise FuncFailed()
# open logs
si = file('/dev/null', 'r')
try:
if bb.debug_level > 0:
so = os.popen("tee \"%s\"" % logfile, "w")
else:
so = file(logfile, 'w')
except OSError, e:
bb.error("opening log file: %s" % e)
pass
se = so
# dup the existing fds so we dont lose them
osi = [os.dup(sys.stdin.fileno()), sys.stdin.fileno()]
oso = [os.dup(sys.stdout.fileno()), sys.stdout.fileno()]
ose = [os.dup(sys.stderr.fileno()), sys.stderr.fileno()]
# replace those fds with our own
os.dup2(si.fileno(), osi[1])
os.dup2(so.fileno(), oso[1])
os.dup2(se.fileno(), ose[1])
# execute function
prevdir = os.getcwd()
if data.getVarFlag(func, "fakeroot", d):
maybe_fakeroot = "PATH=\"%s\" fakeroot " % bb.data.getVar("PATH", d, 1)
else:
maybe_fakeroot = ''
ret = os.system('%ssh -e %s' % (maybe_fakeroot, runfile))
os.chdir(prevdir)
# restore the backups
os.dup2(osi[0], osi[1])
os.dup2(oso[0], oso[1])
os.dup2(ose[0], ose[1])
# close our logs
si.close()
so.close()
se.close()
# close the backup fds
os.close(osi[0])
os.close(oso[0])
os.close(ose[0])
if ret==0:
if bb.debug_level > 0:
os.remove(runfile)
# os.remove(logfile)
return
else:
error("function %s failed" % func)
if data.getVar("BBINCLUDELOGS", d):
error("log data follows (%s)" % logfile)
f = open(logfile, "r")
while True:
l = f.readline()
if l == '':
break
l = l.rstrip()
print '| %s' % l
f.close()
else:
error("see log in %s" % logfile)
raise FuncFailed( logfile )
def exec_task(task, d):
"""Execute an BB 'task'
The primary difference between executing a task versus executing
a function is that a task exists in the task digraph, and therefore
has dependencies amongst other tasks."""
# check if the task is in the graph..
task_graph = data.getVar('_task_graph', d)
if not task_graph:
task_graph = bb.digraph()
data.setVar('_task_graph', task_graph, d)
task_cache = data.getVar('_task_cache', d)
if not task_cache:
task_cache = []
data.setVar('_task_cache', task_cache, d)
if not task_graph.hasnode(task):
raise EventException("Missing node in task graph", InvalidTask(task, d))
# check whether this task needs executing..
if not data.getVarFlag(task, 'force', d):
if stamp_is_current(task, d):
return 1
# follow digraph path up, then execute our way back down
def execute(graph, item):
if data.getVarFlag(item, 'task', d):
if item in task_cache:
return 1
if task != item:
# deeper than toplevel, exec w/ deps
exec_task(item, d)
return 1
try:
debug(1, "Executing task %s" % item)
old_overrides = data.getVar('OVERRIDES', d, 0)
localdata = data.createCopy(d)
data.setVar('OVERRIDES', 'task_%s:%s' % (item, old_overrides), localdata)
data.update_data(localdata)
event.fire(TaskStarted(item, localdata))
exec_func(item, localdata)
event.fire(TaskSucceeded(item, localdata))
task_cache.append(item)
data.setVar('_task_cache', task_cache, d)
except FuncFailed, reason:
note( "Task failed: %s" % reason )
failedevent = TaskFailed(item, d)
event.fire(failedevent)
raise EventException("Function failed in task: %s" % reason, failedevent)
# execute
task_graph.walkdown(task, execute)
# make stamp, or cause event and raise exception
if not data.getVarFlag(task, 'nostamp', d):
mkstamp(task, d)
def stamp_is_current(task, d, checkdeps = 1):
"""Check status of a given task's stamp. returns 0 if it is not current and needs updating."""
task_graph = data.getVar('_task_graph', d)
if not task_graph:
task_graph = bb.digraph()
data.setVar('_task_graph', task_graph, d)
stamp = data.getVar('STAMP', d)
if not stamp:
return 0
stampfile = "%s.%s" % (data.expand(stamp, d), task)
if not os.access(stampfile, os.F_OK):
return 0
if checkdeps == 0:
return 1
import stat
tasktime = os.stat(stampfile)[stat.ST_MTIME]
_deps = []
def checkStamp(graph, task):
# check for existance
if data.getVarFlag(task, 'nostamp', d):
return 1
if not stamp_is_current(task, d, 0):
return 0
depfile = "%s.%s" % (data.expand(stamp, d), task)
deptime = os.stat(depfile)[stat.ST_MTIME]
if deptime > tasktime:
return 0
return 1
return task_graph.walkdown(task, checkStamp)
def md5_is_current(task):
"""Check if a md5 file for a given task is current"""
def mkstamp(task, d):
"""Creates/updates a stamp for a given task"""
stamp = data.getVar('STAMP', d)
if not stamp:
return
stamp = "%s.%s" % (data.expand(stamp, d), task)
mkdirhier(os.path.dirname(stamp))
open(stamp, "w+")
def add_task(task, deps, d):
task_graph = data.getVar('_task_graph', d)
if not task_graph:
task_graph = bb.digraph()
data.setVarFlag(task, 'task', 1, d)
task_graph.addnode(task, None)
for dep in deps:
if not task_graph.hasnode(dep):
task_graph.addnode(dep, None)
task_graph.addnode(task, dep)
# don't assume holding a reference
data.setVar('_task_graph', task_graph, d)
def remove_task(task, kill, d):
"""Remove an BB 'task'.
If kill is 1, also remove tasks that depend on this task."""
task_graph = data.getVar('_task_graph', d)
if not task_graph:
task_graph = bb.digraph()
if not task_graph.hasnode(task):
return
data.delVarFlag(task, 'task', d)
ref = 1
if kill == 1:
ref = 2
task_graph.delnode(task, ref)
data.setVar('_task_graph', task_graph, d)
def task_exists(task, d):
task_graph = data.getVar('_task_graph', d)
if not task_graph:
task_graph = bb.digraph()
data.setVar('_task_graph', task_graph, d)
return task_graph.hasnode(task)
def get_task_data():
return _task_data

580
bitbake/lib/bb/data.py Normal file
View File

@@ -0,0 +1,580 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake 'Data' implementations
Functions for interacting with the data structure used by the
BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2005 Holger Hans Peter Freyther
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
import sys, os, re, time, types
if sys.argv[0][-5:] == "pydoc":
path = os.path.dirname(os.path.dirname(sys.argv[1]))
else:
path = os.path.dirname(os.path.dirname(sys.argv[0]))
sys.path.append(path)
from bb import note, debug, data_smart
_dict_type = data_smart.DataSmart
_dict_p_type = data_smart.DataSmartPackage
class DataDictFull(dict):
"""
This implements our Package Data Storage Interface.
setDirty is a no op as all items are held in memory
"""
def setDirty(self, bbfile, data):
"""
No-Op we assume data was manipulated as some sort of
reference
"""
if not bbfile in self:
raise Exception("File %s was not in dictionary before" % bbfile)
self[bbfile] = data
class DataDictCache:
"""
Databacked Dictionary implementation
"""
def __init__(self, cache_dir, config):
self.cache_dir = cache_dir
self.files = []
self.dirty = {}
self.config = config
def has_key(self,key):
return key in self.files
def keys(self):
return self.files
def __setitem__(self, key, data):
"""
Add the key to the list of known files and
place the data in the cache?
"""
if key in self.files:
return
self.files.append(key)
def __getitem__(self, key):
if not key in self.files:
return None
# if it was dirty we will
if key in self.dirty:
return self.dirty[key]
# not cached yet
return _dict_p_type(self.cache_dir, key,False,self.config)
def setDirty(self, bbfile, data):
"""
Only already added items can be declared dirty!!!
"""
if not bbfile in self.files:
raise Exception("File %s was not in dictionary before" % bbfile)
self.dirty[bbfile] = data
def init():
return _dict_type()
def init_db(cache,name,clean,parent = None):
return _dict_p_type(cache,name,clean,parent)
def init_db_mtime(cache,cache_bbfile):
return _dict_p_type.mtime(cache,cache_bbfile)
def pkgdata(use_cache, cache, config = None):
"""
Return some sort of dictionary to lookup parsed dictionaires
"""
if use_cache:
return DataDictCache(cache, config)
return DataDictFull()
def createCopy(source):
"""Link the source set to the destination
If one does not find the value in the destination set,
search will go on to the source set to get the value.
Value from source are copy-on-write. i.e. any try to
modify one of them will end up putting the modified value
in the destination set.
"""
return source.createCopy()
def initVar(var, d):
"""Non-destructive var init for data structure"""
d.initVar(var)
def setVar(var, value, d):
"""Set a variable to a given value
Example:
>>> d = init()
>>> setVar('TEST', 'testcontents', d)
>>> print getVar('TEST', d)
testcontents
"""
d.setVar(var,value)
def getVar(var, d, exp = 0):
"""Gets the value of a variable
Example:
>>> d = init()
>>> setVar('TEST', 'testcontents', d)
>>> print getVar('TEST', d)
testcontents
"""
return d.getVar(var,exp)
def delVar(var, d):
"""Removes a variable from the data set
Example:
>>> d = init()
>>> setVar('TEST', 'testcontents', d)
>>> print getVar('TEST', d)
testcontents
>>> delVar('TEST', d)
>>> print getVar('TEST', d)
None
"""
d.delVar(var)
def setVarFlag(var, flag, flagvalue, d):
"""Set a flag for a given variable to a given value
Example:
>>> d = init()
>>> setVarFlag('TEST', 'python', 1, d)
>>> print getVarFlag('TEST', 'python', d)
1
"""
d.setVarFlag(var,flag,flagvalue)
def getVarFlag(var, flag, d):
"""Gets given flag from given var
Example:
>>> d = init()
>>> setVarFlag('TEST', 'python', 1, d)
>>> print getVarFlag('TEST', 'python', d)
1
"""
return d.getVarFlag(var,flag)
def delVarFlag(var, flag, d):
"""Removes a given flag from the variable's flags
Example:
>>> d = init()
>>> setVarFlag('TEST', 'testflag', 1, d)
>>> print getVarFlag('TEST', 'testflag', d)
1
>>> delVarFlag('TEST', 'testflag', d)
>>> print getVarFlag('TEST', 'testflag', d)
None
"""
d.delVarFlag(var,flag)
def setVarFlags(var, flags, d):
"""Set the flags for a given variable
Example:
>>> d = init()
>>> myflags = {}
>>> myflags['test'] = 'blah'
>>> setVarFlags('TEST', myflags, d)
>>> print getVarFlag('TEST', 'test', d)
blah
"""
d.setVarFlags(var,flags)
def getVarFlags(var, d):
"""Gets a variable's flags
Example:
>>> d = init()
>>> setVarFlag('TEST', 'test', 'blah', d)
>>> print getVarFlags('TEST', d)['test']
blah
"""
return d.getVarFlags(var)
def delVarFlags(var, d):
"""Removes a variable's flags
Example:
>>> data = init()
>>> setVarFlag('TEST', 'testflag', 1, data)
>>> print getVarFlag('TEST', 'testflag', data)
1
>>> delVarFlags('TEST', data)
>>> print getVarFlags('TEST', data)
None
"""
d.delVarFlags(var)
def keys(d):
"""Return a list of keys in d
Example:
>>> d = init()
>>> setVar('TEST', 1, d)
>>> setVar('MOO' , 2, d)
>>> setVarFlag('TEST', 'test', 1, d)
>>> keys(d)
['TEST', 'MOO']
"""
return d.keys()
def getData(d):
"""Returns the data object used"""
return d
def setData(newData, d):
"""Sets the data object to the supplied value"""
d = newData
__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
def expand(s, d, varname = None):
"""Variable expansion using the data store.
Example:
Standard expansion:
>>> d = init()
>>> setVar('A', 'sshd', d)
>>> print expand('/usr/bin/${A}', d)
/usr/bin/sshd
Python expansion:
>>> d = init()
>>> print expand('result: ${@37 * 72}', d)
result: 2664
Shell expansion:
>>> d = init()
>>> print expand('${TARGET_MOO}', d)
${TARGET_MOO}
>>> setVar('TARGET_MOO', 'yupp', d)
>>> print expand('${TARGET_MOO}',d)
yupp
>>> setVar('SRC_URI', 'http://somebug.${TARGET_MOO}', d)
>>> delVar('TARGET_MOO', d)
>>> print expand('${SRC_URI}', d)
http://somebug.${TARGET_MOO}
"""
def var_sub(match):
key = match.group()[2:-1]
if varname and key:
if varname == key:
raise Exception("variable %s references itself!" % varname)
var = getVar(key, d, 1)
if var is not None:
return var
else:
return match.group()
def python_sub(match):
import bb
code = match.group()[3:-1]
locals()['d'] = d
s = eval(code)
if type(s) == types.IntType: s = str(s)
return s
if type(s) is not types.StringType: # sanity check
return s
while s.find('$') != -1:
olds = s
try:
s = __expand_var_regexp__.sub(var_sub, s)
s = __expand_python_regexp__.sub(python_sub, s)
if s == olds: break
if type(s) is not types.StringType: # sanity check
import bb
bb.error('expansion of %s returned non-string %s' % (olds, s))
except KeyboardInterrupt:
raise
except:
note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
raise
return s
def expandKeys(alterdata, readdata = None):
if readdata == None:
readdata = alterdata
for key in keys(alterdata):
ekey = expand(key, readdata)
if key == ekey:
continue
val = getVar(key, alterdata)
if val is None:
continue
# import copy
# setVarFlags(ekey, copy.copy(getVarFlags(key, readdata)), alterdata)
setVar(ekey, val, alterdata)
for i in ('_append', '_prepend', '_delete'):
dest = getVarFlag(ekey, i, alterdata) or []
src = getVarFlag(key, i, readdata) or []
dest.extend(src)
setVarFlag(ekey, i, dest, alterdata)
delVar(key, alterdata)
def expandData(alterdata, readdata = None):
"""For each variable in alterdata, expand it, and update the var contents.
Replacements use data from readdata.
Example:
>>> a=init()
>>> b=init()
>>> setVar("dlmsg", "dl_dir is ${DL_DIR}", a)
>>> setVar("DL_DIR", "/path/to/whatever", b)
>>> expandData(a, b)
>>> print getVar("dlmsg", a)
dl_dir is /path/to/whatever
"""
if readdata == None:
readdata = alterdata
for key in keys(alterdata):
val = getVar(key, alterdata)
if type(val) is not types.StringType:
continue
expanded = expand(val, readdata)
# print "key is %s, val is %s, expanded is %s" % (key, val, expanded)
if val != expanded:
setVar(key, expanded, alterdata)
import os
def inheritFromOS(d):
"""Inherit variables from the environment."""
# fakeroot needs to be able to set these
non_inherit_vars = [ "LD_LIBRARY_PATH", "LD_PRELOAD" ]
for s in os.environ.keys():
if not s in non_inherit_vars:
try:
setVar(s, os.environ[s], d)
setVarFlag(s, 'matchesenv', '1', d)
except TypeError:
pass
import sys
def emit_var(var, o=sys.__stdout__, d = init(), all=False):
"""Emit a variable to be sourced by a shell."""
if getVarFlag(var, "python", d):
return 0
try:
if all:
oval = getVar(var, d, 0)
val = getVar(var, d, 1)
except KeyboardInterrupt:
raise
except:
excname = str(sys.exc_info()[0])
if excname == "bb.build.FuncFailed":
raise
o.write('# expansion of %s threw %s\n' % (var, excname))
return 0
if all:
o.write('# %s=%s\n' % (var, oval))
if type(val) is not types.StringType:
return 0
if getVarFlag(var, 'matchesenv', d):
return 0
if (var.find("-") != -1 or var.find(".") != -1 or var.find('{') != -1 or var.find('}') != -1 or var.find('+') != -1) and not all:
return 0
val.rstrip()
if not val:
return 0
if getVarFlag(var, "func", d):
# NOTE: should probably check for unbalanced {} within the var
o.write("%s() {\n%s\n}\n" % (var, val))
else:
if getVarFlag(var, "export", d):
o.write('export ')
else:
if not all:
return 0
# if we're going to output this within doublequotes,
# to a shell, we need to escape the quotes in the var
alter = re.sub('"', '\\"', val.strip())
o.write('%s="%s"\n' % (var, alter))
return 1
def emit_env(o=sys.__stdout__, d = init(), all=False):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
env = keys(d)
for e in env:
if getVarFlag(e, "func", d):
continue
emit_var(e, o, d, all) and o.write('\n')
for e in env:
if not getVarFlag(e, "func", d):
continue
emit_var(e, o, d) and o.write('\n')
def update_data(d):
"""Modifies the environment vars according to local overrides and commands.
Examples:
Appending to a variable:
>>> d = init()
>>> setVar('TEST', 'this is a', d)
>>> setVar('TEST_append', ' test', d)
>>> setVar('TEST_append', ' of the emergency broadcast system.', d)
>>> update_data(d)
>>> print getVar('TEST', d)
this is a test of the emergency broadcast system.
Prepending to a variable:
>>> setVar('TEST', 'virtual/libc', d)
>>> setVar('TEST_prepend', 'virtual/tmake ', d)
>>> setVar('TEST_prepend', 'virtual/patcher ', d)
>>> update_data(d)
>>> print getVar('TEST', d)
virtual/patcher virtual/tmake virtual/libc
Overrides:
>>> setVar('TEST_arm', 'target', d)
>>> setVar('TEST_ramses', 'machine', d)
>>> setVar('TEST_local', 'local', d)
>>> setVar('OVERRIDES', 'arm', d)
>>> setVar('TEST', 'original', d)
>>> update_data(d)
>>> print getVar('TEST', d)
target
>>> setVar('OVERRIDES', 'arm:ramses:local', d)
>>> setVar('TEST', 'original', d)
>>> update_data(d)
>>> print getVar('TEST', d)
local
"""
debug(2, "update_data()")
# can't do delete env[...] while iterating over the dictionary, so remember them
dodel = []
overrides = (getVar('OVERRIDES', d, 1) or "").split(':') or []
def applyOverrides(var, d):
if not overrides:
debug(1, "OVERRIDES not defined, nothing to do")
return
val = getVar(var, d)
for o in overrides:
if var.endswith("_" + o):
l = len(o)+1
name = var[:-l]
d[name] = d[var]
for s in keys(d):
applyOverrides(s, d)
sval = getVar(s, d) or ""
# Handle line appends:
for (a, o) in getVarFlag(s, '_append', d) or []:
# maybe the OVERRIDE was not yet added so keep the append
if (o and o in overrides) or not o:
delVarFlag(s, '_append', d)
if o:
if not o in overrides:
continue
sval+=a
setVar(s, sval, d)
# Handle line prepends
for (a, o) in getVarFlag(s, '_prepend', d) or []:
# maybe the OVERRIDE was not yet added so keep the append
if (o and o in overrides) or not o:
delVarFlag(s, '_prepend', d)
if o:
if not o in overrides:
continue
sval=a+sval
setVar(s, sval, d)
# Handle line deletions
name = s + "_delete"
nameval = getVar(name, d)
if nameval:
sval = getVar(s, d)
if sval:
new = ''
pattern = nameval.replace('\n','').strip()
for line in sval.split('\n'):
if line.find(pattern) == -1:
new = new + '\n' + line
setVar(s, new, d)
dodel.append(name)
# delete all environment vars no longer needed
for s in dodel:
delVar(s, d)
def inherits_class(klass, d):
val = getVar('__inherit_cache', d) or ""
if os.path.join('classes', '%s.bbclass' % klass) in val.split():
return True
return False
def _test():
"""Start a doctest run on this module"""
import doctest
from bb import data
doctest.testmod(data)
if __name__ == "__main__":
_test()

View File

@@ -0,0 +1,351 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake Smart Dictionary Implementation
Functions for interacting with the data structure used by the
BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2004, 2005 Seb Frankengul
Copyright (C) 2005 Holger Hans Peter Freyther
Copyright (C) 2005 Uli Luckas
Copyright (C) 2005 ROAD GmbH
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
import copy, os, re, sys, time, types
from bb import note, debug, fatal
try:
import cPickle as pickle
except ImportError:
import pickle
print "NOTE: Importing cPickle failed. Falling back to a very slow implementation."
__setvar_keyword__ = ["_append","_prepend","_delete"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_delete)(_(?P<add>.*))?')
__expand_var_regexp__ = re.compile(r"\${[^{}]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
class DataSmart:
def __init__(self):
self.dict = {}
def expand(self,s, varname):
def var_sub(match):
key = match.group()[2:-1]
if varname and key:
if varname == key:
raise Exception("variable %s references itself!" % varname)
var = self.getVar(key, 1)
if var is not None:
return var
else:
return match.group()
def python_sub(match):
import bb
code = match.group()[3:-1]
locals()['d'] = self
s = eval(code)
if type(s) == types.IntType: s = str(s)
return s
if type(s) is not types.StringType: # sanity check
return s
while s.find('$') != -1:
olds = s
try:
s = __expand_var_regexp__.sub(var_sub, s)
s = __expand_python_regexp__.sub(python_sub, s)
if s == olds: break
if type(s) is not types.StringType: # sanity check
import bb
bb.error('expansion of %s returned non-string %s' % (olds, s))
except KeyboardInterrupt:
raise
except:
note("%s:%s while evaluating:\n%s" % (sys.exc_info()[0], sys.exc_info()[1], s))
raise
return s
def initVar(self, var):
if not var in self.dict:
self.dict[var] = {}
def pickle_prep(self, cfg):
if "_data" in self.dict:
if self.dict["_data"] == cfg:
self.dict["_data"] = "cfg";
else: # this is an unknown array for the moment
pass
def unpickle_prep(self, cfg):
if "_data" in self.dict:
if self.dict["_data"] == "cfg":
self.dict["_data"] = cfg;
def _findVar(self,var):
_dest = self.dict
while (_dest and var not in _dest):
if not "_data" in _dest:
_dest = None
break
_dest = _dest["_data"]
if _dest and var in _dest:
return _dest[var]
return None
def _copyVar(self,var,name):
local_var = self._findVar(var)
if local_var:
self.dict[name] = copy.copy(local_var)
else:
debug(1,"Warning, _copyVar %s to %s, %s does not exists" % (var,name,var))
def _makeShadowCopy(self, var):
if var in self.dict:
return
local_var = self._findVar(var)
if local_var:
self.dict[var] = copy.copy(local_var)
else:
self.initVar(var)
def setVar(self,var,value):
match = __setvar_regexp__.match(var)
if match and match.group("keyword") in __setvar_keyword__:
base = match.group('base')
keyword = match.group("keyword")
override = match.group('add')
l = self.getVarFlag(base, keyword) or []
if override == 'delete':
if l.count([value, None]):
del l[l.index([value, None])]
l.append([value, override])
self.setVarFlag(base, match.group("keyword"), l)
return
if not var in self.dict:
self._makeShadowCopy(var)
if self.getVarFlag(var, 'matchesenv'):
self.delVarFlag(var, 'matchesenv')
self.setVarFlag(var, 'export', 1)
# setting var
self.dict[var]["content"] = value
def getVar(self,var,exp):
value = self.getVarFlag(var,"content")
if exp and value:
return self.expand(value,var)
return value
def delVar(self,var):
self.dict[var] = {}
def setVarFlag(self,var,flag,flagvalue):
if not var in self.dict:
self._makeShadowCopy(var)
self.dict[var][flag] = flagvalue
def getVarFlag(self,var,flag):
local_var = self._findVar(var)
if local_var:
if flag in local_var:
return copy.copy(local_var[flag])
return None
def delVarFlag(self,var,flag):
local_var = self._findVar(var)
if not local_var:
return
if not var in self.dict:
self._makeShadowCopy(var)
if var in self.dict and flag in self.dict[var]:
del self.dict[var][flag]
def setVarFlags(self,var,flags):
if not var in self.dict:
self._makeShadowCopy(var)
for i in flags.keys():
if i == "content":
continue
self.dict[var][i] = flags[i]
def getVarFlags(self,var):
local_var = self._findVar(var)
flags = {}
if local_var:
for i in self.dict[var].keys():
if i == "content":
continue
flags[i] = self.dict[var][i]
if len(flags) == 0:
return None
return flags
def delVarFlags(self,var):
if not var in self.dict:
self._makeShadowCopy(var)
if var in self.dict:
content = None
# try to save the content
if "content" in self.dict[var]:
content = self.dict[var]["content"]
self.dict[var] = {}
self.dict[var]["content"] = content
else:
del self.dict[var]
def createCopy(self):
"""
Create a copy of self by setting _data to self
"""
# we really want this to be a DataSmart...
data = DataSmart()
data.dict["_data"] = self.dict
return data
# Dictionary Methods
def keys(self):
def _keys(d, mykey):
if "_data" in d:
_keys(d["_data"],mykey)
for key in d.keys():
if key != "_data":
mykey[key] = None
keytab = {}
_keys(self.dict,keytab)
return keytab.keys()
def __getitem__(self,item):
start = self.dict
while start:
if item in start:
return start[item]
elif "_data" in start:
start = start["_data"]
else:
start = None
return None
def __setitem__(self,var,data):
self._makeShadowCopy(var)
self.dict[var] = data
class DataSmartPackage(DataSmart):
"""
Persistent Data Storage
"""
def sanitize_filename(bbfile):
return bbfile.replace( '/', '_' )
sanitize_filename = staticmethod(sanitize_filename)
def unpickle(self):
"""
Restore the dict from memory
"""
cache_bbfile = self.sanitize_filename(self.bbfile)
p = pickle.Unpickler( file("%s/%s"%(self.cache,cache_bbfile),"rb"))
self.dict = p.load()
self.unpickle_prep()
funcstr = self.getVar('__functions__', 0)
if funcstr:
comp = compile(funcstr, "<pickled>", "exec")
exec comp in __builtins__
def linkDataSet(self):
if not self.parent == None:
# assume parent is a DataSmartInstance
self.dict["_data"] = self.parent.dict
def __init__(self,cache,name,clean,parent):
"""
Construct a persistent data instance
"""
#Initialize the dictionary
DataSmart.__init__(self)
self.cache = cache
self.bbfile = os.path.abspath( name )
self.parent = parent
# Either unpickle the data or do copy on write
if clean:
self.linkDataSet()
else:
self.unpickle()
def commit(self, mtime):
"""
Save the package to a permanent storage
"""
self.pickle_prep()
cache_bbfile = self.sanitize_filename(self.bbfile)
p = pickle.Pickler(file("%s/%s" %(self.cache,cache_bbfile), "wb" ), -1 )
p.dump( self.dict )
self.unpickle_prep()
def mtime(cache,bbfile):
cache_bbfile = DataSmartPackage.sanitize_filename(bbfile)
try:
return os.stat( "%s/%s" % (cache,cache_bbfile) )[8]
except OSError:
return 0
mtime = staticmethod(mtime)
def pickle_prep(self):
"""
If self.dict contains a _data key and it is a configuration
we will remember we had a configuration instance attached
"""
if "_data" in self.dict:
if self.dict["_data"] == self.parent:
dest["_data"] = "cfg"
def unpickle_prep(self):
"""
If we had a configuration instance attached, we will reattach it
"""
if "_data" in self.dict:
if self.dict["_data"] == "cfg":
self.dict["_data"] = self.parent

210
bitbake/lib/bb/event.py Normal file
View File

@@ -0,0 +1,210 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake 'Event' implementation
Classes and functions for manipulating 'events' in the
BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
"""
import os, re
import bb.data
class Event:
"""Base class for events"""
type = "Event"
def __init__(self, d = bb.data.init()):
self._data = d
def getData(self):
return self._data
def setData(self, data):
self._data = data
data = property(getData, setData, None, "data property")
NotHandled = 0
Handled = 1
handlers = []
def tmpHandler(event):
"""Default handler for code events"""
return NotHandled
def defaultTmpHandler():
tmp = "def tmpHandler(e):\n\t\"\"\"heh\"\"\"\n\treturn 0"
comp = compile(tmp, "tmpHandler(e)", "exec")
return comp
def fire(event):
"""Fire off an Event"""
for h in handlers:
if type(h).__name__ == "code":
exec(h)
if tmpHandler(event) == Handled:
return Handled
else:
if h(event) == Handled:
return Handled
return NotHandled
def register(handler):
"""Register an Event handler"""
if handler is not None:
# handle string containing python code
if type(handler).__name__ == "str":
return registerCode(handler)
# prevent duplicate registration
if not handler in handlers:
handlers.append(handler)
def registerCode(handlerStr):
"""Register a 'code' Event.
Deprecated interface; call register instead.
Expects to be passed python code as a string, which will
be passed in turn to compile() and then exec(). Note that
the code will be within a function, so should have had
appropriate tabbing put in place."""
tmp = "def tmpHandler(e):\n%s" % handlerStr
comp = compile(tmp, "tmpHandler(e)", "exec")
# prevent duplicate registration
if not comp in handlers:
handlers.append(comp)
def remove(handler):
"""Remove an Event handler"""
for h in handlers:
if type(handler).__name__ == "str":
return removeCode(handler)
if handler is h:
handlers.remove(handler)
def removeCode(handlerStr):
"""Remove a 'code' Event handler
Deprecated interface; call remove instead."""
tmp = "def tmpHandler(e):\n%s" % handlerStr
comp = compile(tmp, "tmpHandler(e)", "exec")
handlers.remove(comp)
def getName(e):
"""Returns the name of a class or class instance"""
if getattr(e, "__name__", None) == None:
return e.__class__.__name__
else:
return e.__name__
class PkgBase(Event):
"""Base class for package events"""
def __init__(self, t, d = {}):
self._pkg = t
Event.__init__(self, d)
def getPkg(self):
return self._pkg
def setPkg(self, pkg):
self._pkg = pkg
pkg = property(getPkg, setPkg, None, "pkg property")
class BuildBase(Event):
"""Base class for bbmake run events"""
def __init__(self, n, p, c):
self._name = n
self._pkgs = p
Event.__init__(self, c)
def getPkgs(self):
return self._pkgs
def setPkgs(self, pkgs):
self._pkgs = pkgs
def getName(self):
return self._name
def setName(self, name):
self._name = name
def getCfg(self):
return self.data
def setCfg(self, cfg):
self.data = cfg
pkgs = property(getPkgs, setPkgs, None, "pkgs property")
name = property(getName, setName, None, "name property")
cfg = property(getCfg, setCfg, None, "cfg property")
class DepBase(PkgBase):
"""Base class for dependency events"""
def __init__(self, t, data, d):
self._dep = d
PkgBase.__init__(self, t, data)
def getDep(self):
return self._dep
def setDep(self, dep):
self._dep = dep
dep = property(getDep, setDep, None, "dep property")
class PkgStarted(PkgBase):
"""Package build started"""
class PkgFailed(PkgBase):
"""Package build failed"""
class PkgSucceeded(PkgBase):
"""Package build completed"""
class BuildStarted(BuildBase):
"""bbmake build run started"""
class BuildCompleted(BuildBase):
"""bbmake build run completed"""
class UnsatisfiedDep(DepBase):
"""Unsatisfied Dependency"""
class RecursiveDep(DepBase):
"""Recursive Dependency"""
class MultipleProviders(PkgBase):
"""Multiple Providers"""

656
bitbake/lib/bb/fetch.py Normal file
View File

@@ -0,0 +1,656 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake 'Fetch' implementations
Classes for obtaining upstream sources for the
BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
import os, re
import bb
from bb import data
class FetchError(Exception):
"""Exception raised when a download fails"""
class NoMethodError(Exception):
"""Exception raised when there is no method to obtain a supplied url or set of urls"""
class MissingParameterError(Exception):
"""Exception raised when a fetch method is missing a critical parameter in the url"""
class MD5SumError(Exception):
"""Exception raised when a MD5SUM of a file does not match the expected one"""
def uri_replace(uri, uri_find, uri_replace, d):
# bb.note("uri_replace: operating on %s" % uri)
if not uri or not uri_find or not uri_replace:
bb.debug(1, "uri_replace: passed an undefined value, not replacing")
uri_decoded = list(bb.decodeurl(uri))
uri_find_decoded = list(bb.decodeurl(uri_find))
uri_replace_decoded = list(bb.decodeurl(uri_replace))
result_decoded = ['','','','','',{}]
for i in uri_find_decoded:
loc = uri_find_decoded.index(i)
result_decoded[loc] = uri_decoded[loc]
import types
if type(i) == types.StringType:
import re
if (re.match(i, uri_decoded[loc])):
result_decoded[loc] = re.sub(i, uri_replace_decoded[loc], uri_decoded[loc])
if uri_find_decoded.index(i) == 2:
if d:
localfn = bb.fetch.localpath(uri, d)
if localfn:
result_decoded[loc] = os.path.dirname(result_decoded[loc]) + "/" + os.path.basename(bb.fetch.localpath(uri, d))
# bb.note("uri_replace: matching %s against %s and replacing with %s" % (i, uri_decoded[loc], uri_replace_decoded[loc]))
else:
# bb.note("uri_replace: no match")
return uri
# else:
# for j in i.keys():
# FIXME: apply replacements against options
return bb.encodeurl(result_decoded)
methods = []
def init(urls = [], d = None):
if d == None:
bb.debug(2,"BUG init called with None as data object!!!")
return
for m in methods:
m.urls = []
for u in urls:
for m in methods:
m.data = d
if m.supports(u, d):
m.urls.append(u)
def go(d):
"""Fetch all urls"""
for m in methods:
if m.urls:
m.go(d)
def localpaths(d):
"""Return a list of the local filenames, assuming successful fetch"""
local = []
for m in methods:
for u in m.urls:
local.append(m.localpath(u, d))
return local
def localpath(url, d):
for m in methods:
if m.supports(url, d):
return m.localpath(url, d)
return url
class Fetch(object):
"""Base class for 'fetch'ing data"""
def __init__(self, urls = []):
self.urls = []
for url in urls:
if self.supports(bb.decodeurl(url), d) is 1:
self.urls.append(url)
def supports(url, d):
"""Check to see if this fetch class supports a given url.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
return 0
supports = staticmethod(supports)
def localpath(url, d):
"""Return the local filename of a given url assuming a successful fetch.
"""
return url
localpath = staticmethod(localpath)
def setUrls(self, urls):
self.__urls = urls
def getUrls(self):
return self.__urls
urls = property(getUrls, setUrls, None, "Urls property")
def setData(self, data):
self.__data = data
def getData(self):
return self.__data
data = property(getData, setData, None, "Data property")
def go(self, urls = []):
"""Fetch urls"""
raise NoMethodError("Missing implementation for url")
class Wget(Fetch):
"""Class to fetch urls via 'wget'"""
def supports(url, d):
"""Check to see if a given url can be fetched using wget.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
return type in ['http','https','ftp']
supports = staticmethod(supports)
def localpath(url, d):
# strip off parameters
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
if "localpath" in parm:
# if user overrides local path, use it.
return parm["localpath"]
url = bb.encodeurl([type, host, path, user, pswd, {}])
return os.path.join(data.getVar("DL_DIR", d), os.path.basename(url))
localpath = staticmethod(localpath)
def go(self, d, urls = []):
"""Fetch urls"""
def md5_sum(basename, data):
"""
Fast and incomplete OVERRIDE implementation for MD5SUM handling
MD5SUM_basename = "SUM" and fallback to MD5SUM_basename
"""
var = "MD5SUM_%s" % basename
return getVar(var, data) or get("MD5SUM",data)
def fetch_uri(uri, basename, dl, md5, parm, d):
if os.path.exists(dl):
# file exists, but we didnt complete it.. trying again..
fetchcmd = data.getVar("RESUMECOMMAND", d, 1)
else:
fetchcmd = data.getVar("FETCHCOMMAND", d, 1)
bb.note("fetch " + uri)
fetchcmd = fetchcmd.replace("${URI}", uri)
fetchcmd = fetchcmd.replace("${FILE}", basename)
bb.debug(2, "executing " + fetchcmd)
ret = os.system(fetchcmd)
if ret != 0:
return False
# check if sourceforge did send us to the mirror page
dl_dir = data.getVar("DL_DIR", d, True)
if not os.path.exists(dl):
os.system("rm %s*" % dl) # FIXME shell quote it
bb.debug(2,"sourceforge.net send us to the mirror on %s" % basename)
return False
# supposedly complete.. write out md5sum
if bb.which(data.getVar('PATH', d), 'md5sum'):
try:
md5pipe = os.popen('md5sum ' + dl)
md5data = (md5pipe.readline().split() or [ "" ])[0]
md5pipe.close()
except OSError:
md5data = ""
md5out = file(md5, 'w')
md5out.write(md5data)
md5out.close()
else:
md5out = file(md5, 'w')
md5out.write("")
md5out.close()
return True
if not urls:
urls = self.urls
localdata = data.createCopy(d)
data.setVar('OVERRIDES', "wget:" + data.getVar('OVERRIDES', localdata), localdata)
data.update_data(localdata)
for uri in urls:
completed = 0
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(uri, localdata))
basename = os.path.basename(path)
dl = self.localpath(uri, d)
dl = data.expand(dl, localdata)
md5 = dl + '.md5'
if os.path.exists(md5):
# complete, nothing to see here..
continue
premirrors = [ i.split() for i in (data.getVar('PREMIRRORS', localdata, 1) or "").split('\n') if i ]
for (find, replace) in premirrors:
newuri = uri_replace(uri, find, replace, d)
if newuri != uri:
if fetch_uri(newuri, basename, dl, md5, parm, localdata):
completed = 1
break
if completed:
continue
if fetch_uri(uri, basename, dl, md5, parm, localdata):
continue
# try mirrors
mirrors = [ i.split() for i in (data.getVar('MIRRORS', localdata, 1) or "").split('\n') if i ]
for (find, replace) in mirrors:
newuri = uri_replace(uri, find, replace, d)
if newuri != uri:
if fetch_uri(newuri, basename, dl, md5, parm, localdata):
completed = 1
break
if not completed:
raise FetchError(uri)
del localdata
methods.append(Wget())
class Cvs(Fetch):
"""Class to fetch a module or modules from cvs repositories"""
def supports(url, d):
"""Check to see if a given url can be fetched with cvs.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
return type in ['cvs', 'pserver']
supports = staticmethod(supports)
def localpath(url, d):
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
if "localpath" in parm:
# if user overrides local path, use it.
return parm["localpath"]
if not "module" in parm:
raise MissingParameterError("cvs method needs a 'module' parameter")
else:
module = parm["module"]
if 'tag' in parm:
tag = parm['tag']
else:
tag = ""
if 'date' in parm:
date = parm['date']
else:
if not tag:
date = data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
else:
date = ""
return os.path.join(data.getVar("DL_DIR", d, 1),data.expand('%s_%s_%s_%s.tar.gz' % ( module.replace('/', '.'), host, tag, date), d))
localpath = staticmethod(localpath)
def go(self, d, urls = []):
"""Fetch urls"""
if not urls:
urls = self.urls
localdata = data.createCopy(d)
data.setVar('OVERRIDES', "cvs:%s" % data.getVar('OVERRIDES', localdata), localdata)
data.update_data(localdata)
for loc in urls:
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(loc, localdata))
if not "module" in parm:
raise MissingParameterError("cvs method needs a 'module' parameter")
else:
module = parm["module"]
dlfile = self.localpath(loc, localdata)
dldir = data.getVar('DL_DIR', localdata, 1)
# if local path contains the cvs
# module, consider the dir above it to be the
# download directory
# pos = dlfile.find(module)
# if pos:
# dldir = dlfile[:pos]
# else:
# dldir = os.path.dirname(dlfile)
# setup cvs options
options = []
if 'tag' in parm:
tag = parm['tag']
else:
tag = ""
if 'date' in parm:
date = parm['date']
else:
if not tag:
date = data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
else:
date = ""
if "method" in parm:
method = parm["method"]
else:
method = "pserver"
if "localdir" in parm:
localdir = parm["localdir"]
else:
localdir = module
cvs_rsh = None
if method == "ext":
if "rsh" in parm:
cvs_rsh = parm["rsh"]
tarfn = data.expand('%s_%s_%s_%s.tar.gz' % (module.replace('/', '.'), host, tag, date), localdata)
data.setVar('TARFILES', dlfile, localdata)
data.setVar('TARFN', tarfn, localdata)
dl = os.path.join(dldir, tarfn)
if os.access(dl, os.R_OK):
bb.debug(1, "%s already exists, skipping cvs checkout." % tarfn)
continue
pn = data.getVar('PN', d, 1)
cvs_tarball_stash = None
if pn:
cvs_tarball_stash = data.getVar('CVS_TARBALL_STASH_%s' % pn, d, 1)
if cvs_tarball_stash == None:
cvs_tarball_stash = data.getVar('CVS_TARBALL_STASH', d, 1)
if cvs_tarball_stash:
fetchcmd = data.getVar("FETCHCOMMAND_wget", d, 1)
uri = cvs_tarball_stash + tarfn
bb.note("fetch " + uri)
fetchcmd = fetchcmd.replace("${URI}", uri)
ret = os.system(fetchcmd)
if ret == 0:
bb.note("Fetched %s from tarball stash, skipping checkout" % tarfn)
continue
if date:
options.append("-D %s" % date)
if tag:
options.append("-r %s" % tag)
olddir = os.path.abspath(os.getcwd())
os.chdir(data.expand(dldir, localdata))
# setup cvsroot
if method == "dir":
cvsroot = path
else:
cvsroot = ":" + method + ":" + user
if pswd:
cvsroot += ":" + pswd
cvsroot += "@" + host + ":" + path
data.setVar('CVSROOT', cvsroot, localdata)
data.setVar('CVSCOOPTS', " ".join(options), localdata)
data.setVar('CVSMODULE', module, localdata)
cvscmd = data.getVar('FETCHCOMMAND', localdata, 1)
cvsupdatecmd = data.getVar('UPDATECOMMAND', localdata, 1)
if cvs_rsh:
cvscmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvscmd)
cvsupdatecmd = "CVS_RSH=\"%s\" %s" % (cvs_rsh, cvsupdatecmd)
# create module directory
bb.debug(2, "Fetch: checking for module directory")
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):
bb.note("Update " + loc)
# update sources there
os.chdir(moddir)
myret = os.system(cvsupdatecmd)
else:
bb.note("Fetch " + loc)
# check out sources there
bb.mkdirhier(pkgdir)
os.chdir(pkgdir)
bb.debug(1, "Running %s" % cvscmd)
myret = os.system(cvscmd)
if myret != 0:
try:
os.rmdir(moddir)
except OSError:
pass
raise FetchError(module)
os.chdir(moddir)
os.chdir('..')
# tar them up to a defined filename
myret = os.system("tar -czf %s %s" % (os.path.join(dldir,tarfn), os.path.basename(moddir)))
if myret != 0:
try:
os.unlink(tarfn)
except OSError:
pass
os.chdir(olddir)
del localdata
methods.append(Cvs())
class Bk(Fetch):
def supports(url, d):
"""Check to see if a given url can be fetched via bitkeeper.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
return type in ['bk']
supports = staticmethod(supports)
methods.append(Bk())
class Local(Fetch):
def supports(url, d):
"""Check to see if a given url can be fetched in the local filesystem.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
return type in ['file','patch']
supports = staticmethod(supports)
def localpath(url, d):
"""Return the local filename of a given url assuming a successful fetch.
"""
path = url.split("://")[1]
newpath = path
if path[0] != "/":
filespath = data.getVar('FILESPATH', d, 1)
if filespath:
newpath = bb.which(filespath, path)
if not newpath:
filesdir = data.getVar('FILESDIR', d, 1)
if filesdir:
newpath = os.path.join(filesdir, path)
return newpath
localpath = staticmethod(localpath)
def go(self, urls = []):
"""Fetch urls (no-op for Local method)"""
# no need to fetch local files, we'll deal with them in place.
return 1
methods.append(Local())
class Svn(Fetch):
"""Class to fetch a module or modules from svn repositories"""
def supports(url, d):
"""Check to see if a given url can be fetched with svn.
Expects supplied url in list form, as outputted by bb.decodeurl().
"""
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
return type in ['svn']
supports = staticmethod(supports)
def localpath(url, d):
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(url, d))
if "localpath" in parm:
# if user overrides local path, use it.
return parm["localpath"]
if not "module" in parm:
raise MissingParameterError("svn method needs a 'module' parameter")
else:
module = parm["module"]
if 'rev' in parm:
revision = parm['rev']
else:
revision = ""
date = data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
return os.path.join(data.getVar("DL_DIR", d, 1),data.expand('%s_%s_%s_%s_%s.tar.gz' % ( module.replace('/', '.'), host, path.replace('/','.'), revision, date), d))
localpath = staticmethod(localpath)
def go(self, d, urls = []):
"""Fetch urls"""
if not urls:
urls = self.urls
localdata = data.createCopy(d)
data.setVar('OVERRIDES', "svn:%s" % data.getVar('OVERRIDES', localdata), localdata)
data.update_data(localdata)
for loc in urls:
(type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(loc, localdata))
if not "module" in parm:
raise MissingParameterError("svn method needs a 'module' parameter")
else:
module = parm["module"]
dlfile = self.localpath(loc, localdata)
dldir = data.getVar('DL_DIR', localdata, 1)
# if local path contains the svn
# module, consider the dir above it to be the
# download directory
# pos = dlfile.find(module)
# if pos:
# dldir = dlfile[:pos]
# else:
# dldir = os.path.dirname(dlfile)
# setup svn options
options = []
if 'rev' in parm:
revision = parm['rev']
else:
revision = ""
date = data.getVar("CVSDATE", d, 1) or data.getVar("DATE", d, 1)
if "method" in parm:
method = parm["method"]
else:
method = "pserver"
if "proto" in parm:
proto = parm["proto"]
else:
proto = "svn"
svn_rsh = None
if method == "ext":
if "rsh" in parm:
svn_rsh = parm["rsh"]
tarfn = data.expand('%s_%s_%s_%s_%s.tar.gz' % (module.replace('/', '.'), host, path.replace('/', '.'), revision, date), localdata)
data.setVar('TARFILES', dlfile, localdata)
data.setVar('TARFN', tarfn, localdata)
dl = os.path.join(dldir, tarfn)
if os.access(dl, os.R_OK):
bb.debug(1, "%s already exists, skipping svn checkout." % tarfn)
continue
svn_tarball_stash = data.getVar('CVS_TARBALL_STASH', d, 1)
if svn_tarball_stash:
fetchcmd = data.getVar("FETCHCOMMAND_wget", d, 1)
uri = svn_tarball_stash + tarfn
bb.note("fetch " + uri)
fetchcmd = fetchcmd.replace("${URI}", uri)
ret = os.system(fetchcmd)
if ret == 0:
bb.note("Fetched %s from tarball stash, skipping checkout" % tarfn)
continue
olddir = os.path.abspath(os.getcwd())
os.chdir(data.expand(dldir, localdata))
# setup svnroot
# svnroot = ":" + method + ":" + user
# if pswd:
# svnroot += ":" + pswd
svnroot = host + path
data.setVar('SVNROOT', svnroot, localdata)
data.setVar('SVNCOOPTS', " ".join(options), localdata)
data.setVar('SVNMODULE', module, localdata)
svncmd = data.getVar('FETCHCOMMAND', localdata, 1)
svncmd = "svn co -r {%s} %s://%s/%s" % (date, proto, svnroot, module)
if revision:
svncmd = "svn co -r %s %s://%s/%s" % (revision, proto, svnroot, module)
if svn_rsh:
svncmd = "svn_RSH=\"%s\" %s" % (svn_rsh, svncmd)
# create temp directory
bb.debug(2, "Fetch: creating temporary directory")
bb.mkdirhier(data.expand('${WORKDIR}', localdata))
data.setVar('TMPBASE', data.expand('${WORKDIR}/oesvn.XXXXXX', localdata), localdata)
tmppipe = os.popen(data.getVar('MKTEMPDIRCMD', localdata, 1) or "false")
tmpfile = tmppipe.readline().strip()
if not tmpfile:
bb.error("Fetch: unable to create temporary directory.. make sure 'mktemp' is in the PATH.")
raise FetchError(module)
# check out sources there
os.chdir(tmpfile)
bb.note("Fetch " + loc)
bb.debug(1, "Running %s" % svncmd)
myret = os.system(svncmd)
if myret != 0:
try:
os.rmdir(tmpfile)
except OSError:
pass
raise FetchError(module)
os.chdir(os.path.join(tmpfile, os.path.dirname(module)))
# tar them up to a defined filename
myret = os.system("tar -czf %s %s" % (os.path.join(dldir,tarfn), os.path.basename(module)))
if myret != 0:
try:
os.unlink(tarfn)
except OSError:
pass
# cleanup
os.system('rm -rf %s' % tmpfile)
os.chdir(olddir)
del localdata
methods.append(Svn())

144
bitbake/lib/bb/manifest.py Normal file
View File

@@ -0,0 +1,144 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# Copyright (C) 2003, 2004 Chris Larson
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
import os, sys
import bb, bb.data
def getfields(line):
fields = {}
fieldmap = ( "pkg", "src", "dest", "type", "mode", "uid", "gid", "major", "minor", "start", "inc", "count" )
for f in xrange(len(fieldmap)):
fields[fieldmap[f]] = None
if not line:
return None
splitline = line.split()
if not len(splitline):
return None
try:
for f in xrange(len(fieldmap)):
if splitline[f] == '-':
continue
fields[fieldmap[f]] = splitline[f]
except IndexError:
pass
return fields
def parse (mfile, d):
manifest = []
while 1:
line = mfile.readline()
if not line:
break
if line.startswith("#"):
continue
fields = getfields(line)
if not fields:
continue
manifest.append(fields)
return manifest
def emit (func, manifest, d):
#str = "%s () {\n" % func
str = ""
for line in manifest:
emittedline = emit_line(func, line, d)
if not emittedline:
continue
str += emittedline + "\n"
# str += "}\n"
return str
def mangle (func, line, d):
import copy
newline = copy.copy(line)
src = bb.data.expand(newline["src"], d)
if src:
if not os.path.isabs(src):
src = "${WORKDIR}/" + src
dest = newline["dest"]
if not dest:
return
if dest.startswith("/"):
dest = dest[1:]
if func is "do_install":
dest = "${D}/" + dest
elif func is "do_populate":
dest = "${WORKDIR}/install/" + newline["pkg"] + "/" + dest
elif func is "do_stage":
varmap = {}
varmap["${bindir}"] = "${STAGING_DIR}/${HOST_SYS}/bin"
varmap["${libdir}"] = "${STAGING_DIR}/${HOST_SYS}/lib"
varmap["${includedir}"] = "${STAGING_DIR}/${HOST_SYS}/include"
varmap["${datadir}"] = "${STAGING_DATADIR}"
matched = 0
for key in varmap.keys():
if dest.startswith(key):
dest = varmap[key] + "/" + dest[len(key):]
matched = 1
if not matched:
newline = None
return
else:
newline = None
return
newline["src"] = src
newline["dest"] = dest
return newline
def emit_line (func, line, d):
import copy
newline = copy.deepcopy(line)
newline = mangle(func, newline, d)
if not newline:
return None
str = ""
type = newline["type"]
mode = newline["mode"]
src = newline["src"]
dest = newline["dest"]
if type is "d":
str = "install -d "
if mode:
str += "-m %s " % mode
str += dest
elif type is "f":
if not src:
return None
if dest.endswith("/"):
str = "install -d "
str += dest + "\n"
str += "install "
else:
str = "install -D "
if mode:
str += "-m %s " % mode
str += src + " " + dest
del newline
return str

View File

@@ -0,0 +1,70 @@
"""
BitBake Parsers
File parsers for the BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2003, 2004 Phil Blundell
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
__all__ = [ 'ParseError', 'SkipPackage', 'cached_mtime', 'mark_dependency',
'supports', 'handle', 'init' ]
handlers = []
class ParseError(Exception):
"""Exception raised when parsing fails"""
class SkipPackage(Exception):
"""Exception raised to skip this package"""
__mtime_cache = {}
def cached_mtime(f):
import os
if not __mtime_cache.has_key(f):
__mtime_cache[f] = os.stat(f)[8]
return __mtime_cache[f]
def mark_dependency(d, f):
import bb, os
if f.startswith('./'):
f = "%s/%s" % (os.getcwd(), f[2:])
deps = (bb.data.getVar('__depends', d) or "").split()
deps.append("%s@%s" % (f, cached_mtime(f)))
bb.data.setVar('__depends', " ".join(deps), d)
def supports(fn, data):
"""Returns true if we have a handler for this file, false otherwise"""
for h in handlers:
if h['supports'](fn, data):
return 1
return 0
def handle(fn, data, include = 0):
"""Call the handler that is appropriate for this file"""
for h in handlers:
if h['supports'](fn, data):
return h['handle'](fn, data, include)
raise ParseError("%s is not a BitBake file" % fn)
def init(fn, data):
for h in handlers:
if h['supports'](fn):
return h['init'](data)
from parse_py import __version__, ConfHandler, BBHandler

View File

@@ -0,0 +1,288 @@
/* bbf.flex
written by Marc Singer
6 January 2005
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
DESCRIPTION
-----------
flex lexer specification for a BitBake input file parser.
Unfortunately, flex doesn't welcome comments within the rule sets.
I say unfortunately because this lexer is unreasonably complex and
comments would make the code much easier to comprehend.
The BitBake grammar is not regular. In order to interpret all
of the available input files, the lexer maintains much state as it
parses. There are places where this lexer will emit tokens that
are invalid. The parser will tend to catch these.
The lexer requires C++ at the moment. The only reason for this has
to do with a very small amount of managed state. Producing a C
lexer should be a reasonably easy task as long as the %reentrant
option is used.
NOTES
-----
o RVALUES. There are three kinds of RVALUES. There are unquoted
values, double quote enclosed strings, and single quote
strings. Quoted strings may contain unescaped quotes (of either
type), *and* any type may span more than one line by using a
continuation '\' at the end of the line. This requires us to
recognize all types of values with a single expression.
Moreover, the only reason to quote a value is to include
trailing or leading whitespace. Whitespace within a value is
preserved, ugh.
o CLASSES. C_ patterns define classes. Classes ought not include
a repitition operator, instead letting the reference to the class
define the repitition count.
C_SS - symbol start
C_SB - symbol body
C_SP - whitespace
*/
%option never-interactive
%option yylineno
%option noyywrap
%option reentrant stack
%{
#include "token.h"
#include "lexer.h"
#include <ctype.h>
extern void *bbparseAlloc(void *(*mallocProc)(size_t));
extern void bbparseFree(void *p, void (*freeProc)(void*));
extern void *bbparseAlloc(void *(*mallocProc)(size_t));
extern void *bbparse(void*, int, token_t, lex_t*);
extern void bbparseTrace(FILE *TraceFILE, char *zTracePrompt);
//static const char* rgbInput;
//static size_t cbInput;
int lineError;
int errorParse;
enum {
errorNone = 0,
errorUnexpectedInput,
errorUnsupportedFeature,
};
#define YY_EXTRA_TYPE lex_t*
/* Read from buffer */
#define YY_INPUT(buf,result,max_size) \
{ yyextra->input(buf, &result, max_size); }
//#define YY_DECL static size_t yylex ()
#define ERROR(e) \
do { lineError = yylineno; errorParse = e; yyterminate (); } while (0)
static const char* fixup_escapes (const char* sz);
%}
C_SP [ \t]
COMMENT #.*\n
OP_ASSIGN "="
OP_IMMEDIATE ":="
OP_PREPEND "=+"
OP_APPEND "+="
OP_COND "?="
B_OPEN "{"
B_CLOSE "}"
K_ADDTASK "addtask"
K_ADDHANDLER "addhandler"
K_AFTER "after"
K_BEFORE "before"
K_DEF "def"
K_INCLUDE "include"
K_INHERIT "inherit"
K_PYTHON "python"
K_FAKEROOT "fakeroot"
K_EXPORT "export"
K_EXPORT_FUNC "EXPORT_FUNCTIONS"
STRING \"([^\n\r]|"\\\n")*\"
SSTRING \'([^\n\r]|"\\\n")*\'
VALUE ([^'" \t\n])|([^'" \t\n]([^\n]|(\\\n))*[^'" \t\n])
C_SS [a-zA-Z_]
C_SB [a-zA-Z0-9_+-.]
REF $\{{C_SS}{C_SB}*\}
SYMBOL {C_SS}{C_SB}*
VARIABLE $?{C_SS}({C_SB}*|{REF})*(\[[a-zA-Z0-9_]*\])?
FILENAME ([a-zA-Z_./]|{REF})(([-+a-zA-Z0-9_./]*)|{REF})*
PROC \({C_SP}*\)
%s S_DEF
%s S_DEF_ARGS
%s S_DEF_BODY
%s S_FUNC
%s S_INCLUDE
%s S_INHERIT
%s S_PROC
%s S_RVALUE
%s S_TASK
%%
{OP_APPEND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_APPEND); }
{OP_PREPEND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_PREPEND); }
{OP_IMMEDIATE} { BEGIN S_RVALUE;
yyextra->accept (T_OP_IMMEDIATE); }
{OP_ASSIGN} { BEGIN S_RVALUE;
yyextra->accept (T_OP_ASSIGN); }
{OP_COND} { BEGIN S_RVALUE;
yyextra->accept (T_OP_COND); }
<S_RVALUE>\\\n{C_SP}* { }
<S_RVALUE>{STRING} { BEGIN INITIAL;
size_t cb = yyleng;
while (cb && isspace (yytext[cb - 1]))
--cb;
yytext[cb - 1] = 0;
yyextra->accept (T_STRING, yytext + 1); }
<S_RVALUE>{SSTRING} { BEGIN INITIAL;
size_t cb = yyleng;
while (cb && isspace (yytext[cb - 1]))
--cb;
yytext[cb - 1] = 0;
yyextra->accept (T_STRING, yytext + 1); }
<S_RVALUE>{VALUE} { ERROR (errorUnexpectedInput); }
<S_RVALUE>{C_SP}*\n+ { BEGIN INITIAL;
yyextra->accept (T_STRING, NULL); }
{K_INCLUDE} { BEGIN S_INCLUDE;
yyextra->accept (T_INCLUDE); }
{K_INHERIT} { BEGIN S_INHERIT;
yyextra->accept (T_INHERIT); }
{K_ADDTASK} { BEGIN S_TASK;
yyextra->accept (T_ADDTASK); }
{K_ADDHANDLER} { yyextra->accept (T_ADDHANDLER); }
{K_EXPORT_FUNC} { BEGIN S_FUNC;
yyextra->accept (T_EXPORT_FUNC); }
<S_TASK>{K_BEFORE} { yyextra->accept (T_BEFORE); }
<S_TASK>{K_AFTER} { yyextra->accept (T_AFTER); }
<INITIAL>{K_EXPORT} { yyextra->accept (T_EXPORT); }
<INITIAL>{K_FAKEROOT} { yyextra->accept (T_FAKEROOT); }
<INITIAL>{K_PYTHON} { yyextra->accept (T_PYTHON); }
{PROC}{C_SP}*{B_OPEN}{C_SP}*\n* { BEGIN S_PROC;
yyextra->accept (T_PROC_OPEN); }
<S_PROC>{B_CLOSE}{C_SP}*\n* { BEGIN INITIAL;
yyextra->accept (T_PROC_CLOSE); }
<S_PROC>([^}][^\n]*)?\n* { yyextra->accept (T_PROC_BODY, yytext); }
{K_DEF} { BEGIN S_DEF; }
<S_DEF>{SYMBOL} { BEGIN S_DEF_ARGS;
yyextra->accept (T_SYMBOL, yytext); }
<S_DEF_ARGS>[^\n:]*: { yyextra->accept (T_DEF_ARGS, yytext); }
<S_DEF_ARGS>{C_SP}*\n { BEGIN S_DEF_BODY; }
<S_DEF_BODY>{C_SP}+[^\n]*\n { yyextra->accept (T_DEF_BODY, yytext); }
<S_DEF_BODY>\n { yyextra->accept (T_DEF_BODY, yytext); }
<S_DEF_BODY>. { BEGIN INITIAL; unput (yytext[0]); }
{COMMENT} { }
<INITIAL>{SYMBOL} { yyextra->accept (T_SYMBOL, yytext); }
<INITIAL>{VARIABLE} { yyextra->accept (T_VARIABLE, yytext); }
<S_TASK>{SYMBOL} { yyextra->accept (T_TSYMBOL, yytext); }
<S_FUNC>{SYMBOL} { yyextra->accept (T_FSYMBOL, yytext); }
<S_INHERIT>{SYMBOL} { yyextra->accept (T_ISYMBOL, yytext); }
<S_INCLUDE>{FILENAME} { BEGIN INITIAL;
yyextra->accept (T_ISYMBOL, yytext); }
<S_TASK>\n { BEGIN INITIAL; }
<S_FUNC>\n { BEGIN INITIAL; }
<S_INHERIT>\n { BEGIN INITIAL; }
[ \t\r\n] /* Insignificant whitespace */
. { ERROR (errorUnexpectedInput); }
/* Check for premature termination */
<<EOF>> { return T_EOF; }
%%
void lex_t::accept (int token, const char* sz)
{
token_t t;
memset (&t, 0, sizeof (t));
t.copyString(sz);
/* tell lemon to parse the token */
parse (parser, token, t, this);
}
int lex_t::line ()const
{
return yyget_lineno (scanner);
}
const char* lex_t::filename ()const
{
return m_fileName;
}
void parse (MappedFile* mf)
{
void* parser = bbparseAlloc (malloc);
yyscan_t scanner;
lex_t lex;
yylex_init (&scanner);
lex.parser = parser;
lex.scanner = scanner;
lex.mf = mf;
lex.rgbInput = mf->m_rgb;
lex.cbInput = mf->m_cb;
lex.parse = bbparse;
yyset_extra (&lex, scanner);
int result = yylex (scanner);
lex.accept (0);
bbparseTrace (NULL, NULL);
if (result != T_EOF)
WARNING ("premature end of file\n");
yylex_destroy (scanner);
bbparseFree (parser, free);
}

View File

@@ -0,0 +1,133 @@
"""
BitBake C Parser Python Code
Copyright (C) 2005 Holger Hans Peter Freyther
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
__version__ = "0xdeadbeef"
class CParser:
"""
The C-based Parser for Bitbake
"""
def __init__(self, data, type):
"""
Constructor
"""
self._data = data
def _syntax_error(self, file, line):
"""
lemon/flex reports an syntax error to us and we will
raise an exception
"""
pass
def _export(self, data):
"""
EXPORT VAR = "MOO"
we will now export VAR
"""
pass
def _assign(self, key, value):
"""
VAR = "MOO"
we will assign moo to VAR
"""
pass
def _assign(self, key, value):
"""
"""
pass
def _append(self, key, value):
"""
VAR += "MOO"
we will append " MOO" to var
"""
pass
def _prepend(self, key, value):
"""
VAR =+ "MOO"
we will prepend "MOO " to var
"""
pass
def _immediate(self, key, value):
"""
VAR := "MOO ${CVSDATE}"
we will assign immediately and expand vars
"""
pass
def _conditional(self, key, value):
"""
"""
pass
def _add_task(self, task, before = None, after = None):
"""
"""
pass
def _include(self, file):
"""
"""
pass
def _inherit(self, file):
"""
"""
pass
def _shell_procedure(self, name, body):
"""
"""
pass
def _python_procedure(self, name, body):
"""
"""
pass
def _fakeroot_procedure(self, name, body):
"""
"""
pass
def _def_procedure(self, a, b, c):
"""
"""
pass
def _export_func(self, name):
"""
"""
pass
def _add_handler(self, handler):
"""
"""
pass

View File

@@ -0,0 +1,161 @@
/* bbp.lemon
written by Marc Singer
6 January 2005
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
DESCRIPTION
-----------
lemon parser specification file for a BitBake input file parser.
Most of the interesting shenanigans are done in the lexer. The
BitBake grammar is not regular. In order to emit tokens that
the parser can properly interpret in LALR fashion, the lexer
manages the interpretation state. This is why there are ISYMBOLs,
SYMBOLS, and TSYMBOLS.
This parser was developed by reading the limited available
documentation for BitBake and by analyzing the available BB files.
There is no assertion of correctness to be made about this parser.
*/
%token_type {token_t}
%name bbparse
%token_prefix T_
%extra_argument {lex_t* lex}
%include {
#include "token.h"
}
%token_destructor { $$.release_this (); }
%syntax_error { printf ("%s:%d: syntax error\n",
lex->filename (), lex->line ()); }
program ::= statements.
statements ::= statements statement.
statements ::= .
variable(r) ::= SYMBOL(s).
{ r.assignString( s.string() );
s.assignString( 0 );
s.release_this(); }
variable(r) ::= VARIABLE(v).
{
r.assignString( v.string() );
v.assignString( 0 );
v.release_this(); }
statement ::= EXPORT variable(s) OP_ASSIGN STRING(v).
{ e_assign( s.string(), v.string() );
e_export( s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_IMMEDIATE STRING(v).
{ e_immediate (s.string(), v.string() );
e_export( s.string() );
s.release_this(); v.release_this(); }
statement ::= EXPORT variable(s) OP_COND STRING(v).
{ e_cond( s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_ASSIGN STRING(v).
{ e_assign( s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_PREPEND STRING(v).
{ e_prepend( s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_APPEND STRING(v).
{ e_append( s.string() , v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_IMMEDIATE STRING(v).
{ e_immediate( s.string(), v.string() );
s.release_this(); v.release_this(); }
statement ::= variable(s) OP_COND STRING(v).
{ e_cond( s.string(), v.string() );
s.release_this(); v.release_this(); }
task ::= TSYMBOL(t) BEFORE TSYMBOL(b) AFTER TSYMBOL(a).
{ e_addtask( t.string(), b.string(), a.string() );
t.release_this(); b.release_this(); a.release_this(); }
task ::= TSYMBOL(t) AFTER TSYMBOL(a) BEFORE TSYMBOL(b).
{ e_addtask( t.string(), b.string(), a.string());
t.release_this(); a.release_this(); b.release_this(); }
task ::= TSYMBOL(t).
{ e_addtask( t.string(), NULL, NULL);
t.release_this();}
task ::= TSYMBOL(t) BEFORE TSYMBOL(b).
{ e_addtask( t.string(), b.string(), NULL);
t.release_this(); b.release_this(); }
task ::= TSYMBOL(t) AFTER TSYMBOL(a).
{ e_addtask( t.string(), NULL, a.string());
t.release_this(); a.release_this(); }
tasks ::= tasks task.
tasks ::= task.
statement ::= ADDTASK tasks.
statement ::= ADDHANDLER SYMBOL(s).
{ e_addhandler( s.string()); s.release_this (); }
func ::= FSYMBOL(f). { e_export_func(f.string()); f.release_this(); }
funcs ::= funcs func.
funcs ::= func.
statement ::= EXPORT_FUNC funcs.
inherit ::= ISYMBOL(i). { e_inherit(i.string() ); i.release_this (); }
inherits ::= inherits inherit.
inherits ::= inherit.
statement ::= INHERIT inherits.
statement ::= INCLUDE ISYMBOL(i).
{ e_include(i.string() ); i.release_this(); }
proc_body(r) ::= proc_body(l) PROC_BODY(b).
{ /* concatenate body lines */
r.assignString( token_t::concatString(l.string(), b.string()) );
l.release_this ();
b.release_this ();
}
proc_body(b) ::= . { b.assignString(0); }
statement ::= variable(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc( p.string(), b.string() );
p.release_this(); b.release_this(); }
statement ::= PYTHON SYMBOL(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_python (p.string(), b.string() );
p.release_this(); b.release_this(); }
statement ::= PYTHON PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_python( NULL, b.string());
b.release_this (); }
statement ::= FAKEROOT SYMBOL(p) PROC_OPEN proc_body(b) PROC_CLOSE.
{ e_proc_fakeroot(p.string(), b.string() );
p.release_this (); b.release_this (); }
def_body(r) ::= def_body(l) DEF_BODY(b).
{ /* concatenate body lines */
r.assignString( token_t::concatString(l.string(), b.string());
l.release_this (); b.release_this ();
}
def_body(b) ::= . { b.sz = 0; }
statement ::= SYMBOL(p) DEF_ARGS(a) def_body(b).
{ e_def( p.string(), a.string(), b.string());
p.release_this(); a.release_this(); b.release_this(); }

View File

@@ -0,0 +1,41 @@
/*
Copyright (C) 2005 Holger Hans Peter Freyther
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LEXER_H
#define LEXER_H
struct lex_t {
void *parser;
void *scanner;
void* (*parse)(void*, int, token_t, lex_t*);
void accept(int token, const char* string = 0);
void input(char *buf, int *result, int_max_size);
int line()const;
const char* filename()const;
private:
const char* m_fileName;
};
#endif

View File

@@ -0,0 +1,83 @@
/*
Copyright (C) 2005 Holger Hans Peter Freyther
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef TOKEN_H
#define TOKEN_H
#define PURE_METHOD
struct token_t {
const char* string()const PURE_METHOD;
static char* concatString(const char* l, const char* r);
void assignString(const char* str);
void copyString(const char* str);
void release_this();
private:
char *m_string;
size_t m_stringLen;
};
inline const char* token_t::string()const
{
return m_string;
}
/*
* append str to the current string
*/
inline char* token_t::concatString(const char* l, const char* r)
{
size_t cb = (l ? strlen (l) : 0) + strlen (r) + 1;
r_sz = new char[cb];
*r_sz = 0;
if (l) strcat (r_sz, l);
strcat (r_sz, r);
return r_sz;
}
inline void token_t::assignString(const char* str)
{
m_string = str;
m_stringLen = str ? strlen(str) : 0;
}
inline void token_t::copyString(const char* str)
{
if( str ) {
m_stringLen = strlen(str);
m_string = new char[m_stringLen+1];
strcpy(m_string, str)
}
}
inline void token_t::release_this()
{
delete m_string;
m_string = 0;
}
#endif

View File

@@ -0,0 +1,378 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""class for handling .bb files
Reads a .bb file and obtains its metadata
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2003, 2004 Phil Blundell
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA."""
import re, bb, os, sys
import bb.fetch, bb.build
from bb import debug, data, fetch, fatal
from ConfHandler import include, localpath, obtain, init
from bb.parse import ParseError
__func_start_regexp__ = re.compile( r"(((?P<py>python)|(?P<fr>fakeroot))\s*)*(?P<func>[\w\.\-\+\{\}\$]+)?\s*\(\s*\)\s*{$" )
__inherit_regexp__ = re.compile( r"inherit\s+(.+)" )
__export_func_regexp__ = re.compile( r"EXPORT_FUNCTIONS\s+(.+)" )
__addtask_regexp__ = re.compile("addtask\s+(?P<func>\w+)\s*((before\s*(?P<before>((.*(?=after))|(.*))))|(after\s*(?P<after>((.*(?=before))|(.*)))))*")
__addhandler_regexp__ = re.compile( r"addhandler\s+(.+)" )
__def_regexp__ = re.compile( r"def\s+(\w+).*:" )
__python_func_regexp__ = re.compile( r"(\s+.*)|(^$)" )
__word__ = re.compile(r"\S+")
__infunc__ = ""
__inpython__ = False
__body__ = []
__bbpath_found__ = 0
__classname__ = ""
classes = [ None, ]
def supports(fn, d):
localfn = localpath(fn, d)
return localfn[-3:] == ".bb" or localfn[-8:] == ".bbclass" or localfn[-4:] == ".inc"
def inherit(files, d):
__inherit_cache = data.getVar('__inherit_cache', d) or ""
fn = ""
lineno = 0
for f in files:
file = data.expand(f, d)
if file[0] != "/" and file[-8:] != ".bbclass":
file = os.path.join('classes', '%s.bbclass' % file)
if not file in __inherit_cache.split():
debug(2, "BB %s:%d: inheriting %s" % (fn, lineno, file))
__inherit_cache += " %s" % file
include(fn, file, d)
data.setVar('__inherit_cache', __inherit_cache, d)
def handle(fn, d, include = 0):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __infunc__, __body__, __bbpath_found__, __residue__
__body__ = []
__bbpath_found__ = 0
__infunc__ = ""
__classname__ = ""
__residue__ = []
if include == 0:
debug(2, "BB " + fn + ": handle(data)")
else:
debug(2, "BB " + fn + ": handle(data, include)")
(root, ext) = os.path.splitext(os.path.basename(fn))
init(d)
if ext == ".bbclass":
__classname__ = root
classes.append(__classname__)
if include != 0:
oldfile = data.getVar('FILE', d)
else:
oldfile = None
fn = obtain(fn, d)
bbpath = (data.getVar('BBPATH', d, 1) or '').split(':')
if not os.path.isabs(fn):
f = None
for p in bbpath:
p = data.expand(p, d)
j = os.path.join(p, fn)
if os.access(j, os.R_OK):
abs_fn = j
f = open(j, 'r')
break
if f is None:
raise IOError("file not found")
else:
f = open(fn,'r')
abs_fn = fn
if ext != ".bbclass":
bbpath.insert(0, os.path.dirname(abs_fn))
data.setVar('BBPATH', ":".join(bbpath), d)
if include:
bb.parse.mark_dependency(d, abs_fn)
if ext != ".bbclass":
data.setVar('FILE', fn, d)
i = (data.getVar("INHERIT", d, 1) or "").split()
if not "base" in i and __classname__ != "base":
i[0:0] = ["base"]
inherit(i, d)
lineno = 0
while 1:
lineno = lineno + 1
s = f.readline()
if not s: break
s = s.rstrip()
feeder(lineno, s, fn, d)
if __inpython__:
# add a blank line to close out any python definition
feeder(lineno + 1, "", fn, d)
if ext == ".bbclass":
classes.remove(__classname__)
else:
if include == 0:
data.expandKeys(d)
data.update_data(d)
anonqueue = data.getVar("__anonqueue", d, 1) or []
for anon in anonqueue:
data.setVar("__anonfunc", anon["content"], d)
data.setVarFlags("__anonfunc", anon["flags"], d)
from bb import build
try:
t = data.getVar('T', d)
data.setVar('T', '${TMPDIR}/', d)
build.exec_func("__anonfunc", d)
data.delVar('T', d)
if t:
data.setVar('T', t, d)
except Exception, e:
bb.debug(1, "executing anonymous function: %s" % e)
raise
data.delVar("__anonqueue", d)
data.delVar("__anonfunc", d)
set_additional_vars(fn, d, include)
data.update_data(d)
for var in data.keys(d):
if data.getVarFlag(var, 'handler', d):
bb.event.register(data.getVar(var, d))
continue
if not data.getVarFlag(var, 'task', d):
continue
deps = data.getVarFlag(var, 'deps', d) or []
postdeps = data.getVarFlag(var, 'postdeps', d) or []
bb.build.add_task(var, deps, d)
for p in postdeps:
pdeps = data.getVarFlag(p, 'deps', d) or []
pdeps.append(var)
data.setVarFlag(p, 'deps', pdeps, d)
bb.build.add_task(p, pdeps, d)
bbpath.pop(0)
if oldfile:
bb.data.setVar("FILE", oldfile, d)
return d
def feeder(lineno, s, fn, d):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__,__infunc__, __body__, __bbpath_found__, classes, bb, __residue__
if __infunc__:
if s == '}':
__body__.append('')
data.setVar(__infunc__, '\n'.join(__body__), d)
data.setVarFlag(__infunc__, "func", 1, d)
if __infunc__ == "__anonymous":
anonqueue = bb.data.getVar("__anonqueue", d) or []
anonitem = {}
anonitem["content"] = bb.data.getVar("__anonymous", d)
anonitem["flags"] = bb.data.getVarFlags("__anonymous", d)
anonqueue.append(anonitem)
bb.data.setVar("__anonqueue", anonqueue, d)
bb.data.delVarFlags("__anonymous", d)
bb.data.delVar("__anonymous", d)
__infunc__ = ""
__body__ = []
else:
__body__.append(s)
return
if __inpython__:
m = __python_func_regexp__.match(s)
if m:
__body__.append(s)
return
else:
text = '\n'.join(__body__)
comp = compile(text, "<bb>", "exec")
exec comp in __builtins__
__body__ = []
__inpython__ = False
funcs = data.getVar('__functions__', d) or ""
data.setVar('__functions__', "%s\n%s" % (funcs, text), d)
# fall through
if s == '' or s[0] == '#': return # skip comments and empty lines
if s[-1] == '\\':
__residue__.append(s[:-1])
return
s = "".join(__residue__) + s
__residue__ = []
m = __func_start_regexp__.match(s)
if m:
__infunc__ = m.group("func") or "__anonymous"
key = __infunc__
if data.getVar(key, d):
# clean up old version of this piece of metadata, as its
# flags could cause problems
data.setVarFlag(key, 'python', None, d)
data.setVarFlag(key, 'fakeroot', None, d)
if m.group("py") is not None:
data.setVarFlag(key, "python", "1", d)
else:
data.delVarFlag(key, "python", d)
if m.group("fr") is not None:
data.setVarFlag(key, "fakeroot", "1", d)
else:
data.delVarFlag(key, "fakeroot", d)
return
m = __def_regexp__.match(s)
if m:
__body__.append(s)
__inpython__ = True
return
m = __export_func_regexp__.match(s)
if m:
fns = m.group(1)
n = __word__.findall(fns)
for f in n:
allvars = []
allvars.append(f)
allvars.append(classes[-1] + "_" + f)
vars = [[ allvars[0], allvars[1] ]]
if len(classes) > 1 and classes[-2] is not None:
allvars.append(classes[-2] + "_" + f)
vars = []
vars.append([allvars[2], allvars[1]])
vars.append([allvars[0], allvars[2]])
for (var, calledvar) in vars:
if data.getVar(var, d) and not data.getVarFlag(var, 'export_func', d):
continue
if data.getVar(var, d):
data.setVarFlag(var, 'python', None, d)
data.setVarFlag(var, 'func', None, d)
for flag in [ "func", "python" ]:
if data.getVarFlag(calledvar, flag, d):
data.setVarFlag(var, flag, data.getVarFlag(calledvar, flag, d), d)
for flag in [ "dirs" ]:
if data.getVarFlag(var, flag, d):
data.setVarFlag(calledvar, flag, data.getVarFlag(var, flag, d), d)
if data.getVarFlag(calledvar, "python", d):
data.setVar(var, "\tbb.build.exec_func('" + calledvar + "', d)\n", d)
else:
data.setVar(var, "\t" + calledvar + "\n", d)
data.setVarFlag(var, 'export_func', '1', d)
return
m = __addtask_regexp__.match(s)
if m:
func = m.group("func")
before = m.group("before")
after = m.group("after")
if func is None:
return
var = "do_" + func
data.setVarFlag(var, "task", 1, d)
if after is not None:
# set up deps for function
data.setVarFlag(var, "deps", after.split(), d)
if before is not None:
# set up things that depend on this func
data.setVarFlag(var, "postdeps", before.split(), d)
return
m = __addhandler_regexp__.match(s)
if m:
fns = m.group(1)
hs = __word__.findall(fns)
for h in hs:
data.setVarFlag(h, "handler", 1, d)
return
m = __inherit_regexp__.match(s)
if m:
files = m.group(1)
n = __word__.findall(files)
inherit(n, d)
return
from bb.parse import ConfHandler
return ConfHandler.feeder(lineno, s, fn, d)
__pkgsplit_cache__={}
def vars_from_file(mypkg, d):
if not mypkg:
return (None, None, None)
if mypkg in __pkgsplit_cache__:
return __pkgsplit_cache__[mypkg]
myfile = os.path.splitext(os.path.basename(mypkg))
parts = myfile[0].split('_')
__pkgsplit_cache__[mypkg] = parts
exp = 3 - len(parts)
tmplist = []
while exp != 0:
exp -= 1
tmplist.append(None)
parts.extend(tmplist)
return parts
def set_additional_vars(file, d, include):
"""Deduce rest of variables, e.g. ${A} out of ${SRC_URI}"""
debug(2,"BB %s: set_additional_vars" % file)
src_uri = data.getVar('SRC_URI', d)
if not src_uri:
return
src_uri = data.expand(src_uri, d)
a = data.getVar('A', d)
if a:
a = data.expand(a, d).split()
else:
a = []
from bb import fetch
try:
fetch.init(src_uri.split(), d)
except fetch.NoMethodError:
pass
except bb.MalformedUrl,e:
raise ParseError("Unable to generate local paths for SRC_URI due to malformed uri: %s" % e)
a += fetch.localpaths(d)
del fetch
data.setVar('A', " ".join(a), d)
# Add us to the handlers list
from bb.parse import handlers
handlers.append({'supports': supports, 'handle': handle, 'init': init})
del handlers

View File

@@ -0,0 +1,199 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""class for handling configuration data files
Reads a .conf file and obtains its metadata
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2003, 2004 Phil Blundell
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA."""
import re, bb.data, os, sys
from bb import debug, fatal
from bb.parse import ParseError
#__config_regexp__ = re.compile( r"(?P<exp>export\s*)?(?P<var>[a-zA-Z0-9\-_+.${}]+)\s*(?P<colon>:)?(?P<ques>\?)?=\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<ques>\?=)|(?P<append>\+=)|(?P<prepend>=\+)|(?P<predot>=\.)|(?P<postdot>\.=)|=)\s*(?P<apo>['\"]?)(?P<value>.*)(?P=apo)$")
__include_regexp__ = re.compile( r"include\s+(.+)" )
def init(data):
if not bb.data.getVar('TOPDIR', data):
bb.data.setVar('TOPDIR', os.getcwd(), data)
if not bb.data.getVar('BBPATH', data):
bb.data.setVar('BBPATH', os.path.join(sys.prefix, 'share', 'bitbake'), data)
def supports(fn, d):
return localpath(fn, d)[-5:] == ".conf"
def localpath(fn, d):
if os.path.exists(fn):
return fn
localfn = None
try:
localfn = bb.fetch.localpath(fn, d)
except bb.MalformedUrl:
pass
if not localfn:
localfn = fn
return localfn
def obtain(fn, data = bb.data.init()):
import sys, bb
fn = bb.data.expand(fn, data)
localfn = bb.data.expand(localpath(fn, data), data)
if localfn != fn:
dldir = bb.data.getVar('DL_DIR', data, 1)
if not dldir:
debug(1, "obtain: DL_DIR not defined")
return localfn
bb.mkdirhier(dldir)
try:
bb.fetch.init([fn])
except bb.fetch.NoMethodError:
(type, value, traceback) = sys.exc_info()
debug(1, "obtain: no method: %s" % value)
return localfn
try:
bb.fetch.go(data)
except bb.fetch.MissingParameterError:
(type, value, traceback) = sys.exc_info()
debug(1, "obtain: missing parameters: %s" % value)
return localfn
except bb.fetch.FetchError:
(type, value, traceback) = sys.exc_info()
debug(1, "obtain: failed: %s" % value)
return localfn
return localfn
def include(oldfn, fn, data = bb.data.init()):
if oldfn == fn: # prevent infinate recursion
return None
import bb
fn = bb.data.expand(fn, data)
oldfn = bb.data.expand(oldfn, data)
from bb.parse import handle
try:
ret = handle(fn, data, 1)
except IOError:
debug(2, "CONF file '%s' not found" % fn)
def handle(fn, data = bb.data.init(), include = 0):
if include:
inc_string = "including"
else:
inc_string = "reading"
init(data)
if include == 0:
bb.data.inheritFromOS(data)
oldfile = None
else:
oldfile = bb.data.getVar('FILE', data)
fn = obtain(fn, data)
bbpath = []
if not os.path.isabs(fn):
f = None
vbbpath = bb.data.getVar("BBPATH", data)
if vbbpath:
bbpath += vbbpath.split(":")
for p in bbpath:
currname = os.path.join(bb.data.expand(p, data), fn)
if os.access(currname, os.R_OK):
f = open(currname, 'r')
abs_fn = currname
debug(1, "CONF %s %s" % (inc_string, currname))
break
if f is None:
raise IOError("file not found")
else:
f = open(fn,'r')
debug(1, "CONF %s %s" % (inc_string,fn))
abs_fn = fn
if include:
bb.parse.mark_dependency(data, abs_fn)
lineno = 0
bb.data.setVar('FILE', fn, data)
while 1:
lineno = lineno + 1
s = f.readline()
if not s: break
w = s.strip()
if not w: continue # skip empty lines
s = s.rstrip()
if s[0] == '#': continue # skip comments
while s[-1] == '\\':
s2 = f.readline()[:-1].strip()
lineno = lineno + 1
s = s[:-1] + s2
feeder(lineno, s, fn, data)
if oldfile:
bb.data.setVar('FILE', oldfile, data)
return data
def feeder(lineno, s, fn, data = bb.data.init()):
m = __config_regexp__.match(s)
if m:
groupd = m.groupdict()
key = groupd["var"]
if "exp" in groupd and groupd["exp"] != None:
bb.data.setVarFlag(key, "export", 1, data)
if "ques" in groupd and groupd["ques"] != None:
val = bb.data.getVar(key, data)
if val == None:
val = groupd["value"]
elif "colon" in groupd and groupd["colon"] != None:
val = bb.data.expand(groupd["value"], data)
elif "append" in groupd and groupd["append"] != None:
val = "%s %s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
elif "prepend" in groupd and groupd["prepend"] != None:
val = "%s %s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
elif "postdot" in groupd and groupd["postdot"] != None:
val = "%s%s" % ((bb.data.getVar(key, data) or ""), groupd["value"])
elif "predot" in groupd and groupd["predot"] != None:
val = "%s%s" % (groupd["value"], (bb.data.getVar(key, data) or ""))
else:
val = groupd["value"]
if 'flag' in groupd and groupd['flag'] != None:
# bb.note("setVarFlag(%s, %s, %s, data)" % (key, groupd['flag'], val))
bb.data.setVarFlag(key, groupd['flag'], val, data)
else:
bb.data.setVar(key, val, data)
return
m = __include_regexp__.match(s)
if m:
s = bb.data.expand(m.group(1), data)
# debug(2, "CONF %s:%d: including %s" % (fn, lineno, s))
include(fn, s, data)
return
raise ParseError("%s:%d: unparsed line: '%s'" % (fn, lineno, s));
# Add us to the handlers list
from bb.parse import handlers
handlers.append({'supports': supports, 'handle': handle, 'init': init})
del handlers

View File

@@ -0,0 +1,32 @@
#!/usr/bin/env python
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake Parsers
File parsers for the BitBake build tools.
Copyright (C) 2003, 2004 Chris Larson
Copyright (C) 2003, 2004 Phil Blundell
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
Based on functions from the base bb module, Copyright 2003 Holger Schurig
"""
__version__ = '1.0'
__all__ = [ 'ConfHandler', 'BBHandler']
import ConfHandler
import BBHandler

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

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

71
bitbake/lib/bb/utils.py Normal file
View File

@@ -0,0 +1,71 @@
# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
"""
BitBake Utility Functions
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA.
This file is part of the BitBake build tools.
"""
digits = "0123456789"
ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
import re
def explode_version(s):
r = []
alpha_regexp = re.compile('^([a-zA-Z]+)(.*)$')
numeric_regexp = re.compile('^(\d+)(.*)$')
while (s != ''):
if s[0] in digits:
m = numeric_regexp.match(s)
r.append(int(m.group(1)))
s = m.group(2)
continue
if s[0] in ascii_letters:
m = alpha_regexp.match(s)
r.append(m.group(1))
s = m.group(2)
continue
s = s[1:]
return r
def vercmp_part(a, b):
va = explode_version(a)
vb = explode_version(b)
while True:
if va == []:
ca = None
else:
ca = va.pop(0)
if vb == []:
cb = None
else:
cb = vb.pop(0)
if ca == None and cb == None:
return 0
if ca > cb:
return 1
if ca < cb:
return -1
def vercmp(ta, tb):
(va, ra) = ta
(vb, rb) = tb
r = vercmp_part(va, vb)
if (r == 0):
r = vercmp_part(ra, rb)
return r

69
bitbake/setup.py Executable file
View File

@@ -0,0 +1,69 @@
#!/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) 2003 Chris Larson
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA.
from distutils.core import setup
import os, sys
# bbdir = os.path.join(sys.prefix, 'share', 'bitbake')
# docdir = os.path.join(sys.prefix, 'share', 'doc')
bbdir = os.path.join('bitbake')
docdir = os.path.join('doc')
def clean_doc(type):
origpath = os.path.abspath(os.curdir)
os.chdir(os.path.join(origpath, 'doc', 'manual'))
make = os.environ.get('MAKE') or 'make'
os.system('%s clean-%s' % (make, type))
def generate_doc(type):
origpath = os.path.abspath(os.curdir)
os.chdir(os.path.join(origpath, 'doc', 'manual'))
make = os.environ.get('MAKE') or 'make'
ret = os.system('%s %s' % (make, type))
if ret != 0:
print "ERROR: Unable to generate html documentation."
sys.exit(ret)
os.chdir(origpath)
if 'bdist' in sys.argv[1:]:
generate_doc('html')
sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'lib'))
import bb
import glob
setup(name='bitbake',
version=bb.__version__,
license='GPL',
url='http://developer.berlios.de/projects/bitbake/',
description='BitBake build tool',
long_description='BitBake is a simple tool for the execution of tasks. It is derived from Portage, which is the package management system used by the Gentoo Linux distribution. It is most commonly used to build packages, as it can easily use its rudamentary inheritence to abstract common operations, such as fetching sources, unpacking them, patching them, compiling them, and so on. It is the basis of the OpenEmbedded project, which is being used for OpenZaurus, Familiar, and a number of other Linux distributions.',
author='Chris Larson',
author_email='clarson@elinux.org',
packages=['bb', 'bb.parse', 'bb.parse.parse_py'],
package_dir={'bb': os.path.join('lib', 'bb')},
scripts=[os.path.join('bin', 'bitbake'),
os.path.join('bin', 'bbimage')],
data_files=[(os.path.join(bbdir, 'conf'), [os.path.join('conf', 'bitbake.conf')]),
(os.path.join(bbdir, 'classes'), [os.path.join('classes', 'base.bbclass')]),
(os.path.join(docdir, 'bitbake-%s' % bb.__version__, 'html'), glob.glob(os.path.join('doc', 'manual', 'html', '*.html'))),
(os.path.join(docdir, 'bitbake-%s' % bb.__version__, 'pdf'), glob.glob(os.path.join('doc', 'manual', 'pdf', '*.pdf'))),],
)
if 'bdist' in sys.argv[1:]:
clean_doc('html')

57
build/conf/local.conf.sample Executable file
View File

@@ -0,0 +1,57 @@
# Where to cache the files OE downloads
DL_DIR = "POKYROOT/sources"
BBFILES := "POKYROOT/openembedded/packages/*/*.bb"
BBMASK = ""
PREFERRED_PROVIDERS = "virtual/qte:qte-for-opie virtual/libqpe:libqpe-opie"
PREFERRED_PROVIDERS += " virtual/libsdl:libsdl-qpe"
PREFERRED_PROVIDERS += " virtual/${TARGET_PREFIX}gcc-initial:gcc-cross-initial"
PREFERRED_PROVIDERS += " virtual/${TARGET_PREFIX}gcc:gcc-cross"
PREFERRED_PROVIDERS += " virtual/${TARGET_PREFIX}g++:gcc-cross"
# Uncomment this to specify where BitBake should create its temporary files.
# Note that a full build of everything in OpenEmbedded will take GigaBytes of hard
# disk space, so make sure to free enough space. The default TMPDIR is
# <build directory>/tmp
# TMPDIR = /usr/local/projects/oetmp
# Uncomment this to disable the parse cache (not recommended).
# CACHE = ""
# Uncomment this if you want BitBake to emit debugging output
# BBDEBUG = "yes"
MACHINE = "c7x0"
#MACHINE = "akita"
#MACHINE = "spitz"
#MACHINE = "nokia770"
DISTRO = "poky"
DISTRO_TYPE = "debug"
KERNEL_VERSION = "2.6"
IMAGE_FSTYPES = "jffs2 tar"
# Uncomment these two if you want BitBake to build images useful for debugging.
# DEBUG_BUILD = "1"
# INHIBIT_PACKAGE_STRIP = "1"
# Uncomment these to build a package such that you can use gprof to profile it.
# NOTE: This will only work with 'linux' targets, not
# 'linux-uclibc', as uClibc doesn't provide the necessary
# object files. Also, don't build glibc itself with these
# flags, or it'll fail to build.
#
# PROFILE_OPTIMIZATION = "-pg"
# SELECTED_OPTIMIZATION = "${PROFILE_OPTIMIZATION}"
# LDFLAGS =+ "-pg"
# Uncomment this if you want BitBake to emit the log if a build fails.
BBINCLUDELOGS = "yes"
# Specifies a location to search for pre-generated tarballs when fetching
# a cvs:// URI. Uncomment this, if you not want to pull directly from CVS.
CVS_TARBALL_STASH = "http://www.oesources.org/source/current/"
PREFERRED_VERSION_gcc-cross= "3.4.3"
PREFERRED_VERSION_gcc-cross-initial= "3.4.3"

View File

@@ -0,0 +1,165 @@
inherit base
def autotools_dep_prepend(d):
import bb;
if bb.data.getVar('INHIBIT_AUTOTOOLS_DEPS', d, 1):
return ''
pn = bb.data.getVar('PN', d, 1)
deps = ''
if pn in ['autoconf-native', 'automake-native']:
return deps
deps += 'autoconf-native automake-native '
if not pn in ['libtool', 'libtool-native', 'libtool-cross']:
deps += 'libtool-native '
return deps + 'gnu-config-native '
EXTRA_OEMAKE = ""
DEPENDS_prepend = "${@autotools_dep_prepend(d)}"
acpaths = "default"
EXTRA_AUTORECONF = "--exclude=autopoint"
def autotools_set_crosscompiling(d):
import bb
if not bb.data.inherits_class('native', d):
return " cross_compiling=yes"
return ""
# EXTRA_OECONF_append = "${@autotools_set_crosscompiling(d)}"
oe_runconf () {
if [ -x ${S}/configure ] ; then
cfgcmd="${S}/configure \
--build=${BUILD_SYS} \
--host=${HOST_SYS} \
--target=${TARGET_SYS} \
--prefix=${prefix} \
--exec_prefix=${exec_prefix} \
--bindir=${bindir} \
--sbindir=${sbindir} \
--libexecdir=${libexecdir} \
--datadir=${datadir} \
--sysconfdir=${sysconfdir} \
--sharedstatedir=${sharedstatedir} \
--localstatedir=${localstatedir} \
--libdir=${libdir} \
--includedir=${includedir} \
--oldincludedir=${oldincludedir} \
--infodir=${infodir} \
--mandir=${mandir} \
${EXTRA_OECONF} \
$@"
oenote "Running $cfgcmd..."
$cfgcmd || oefatal "oe_runconf failed"
else
oefatal "no configure script found"
fi
}
autotools_do_configure() {
case ${PN} in
autoconf*)
;;
automake*)
;;
*)
# WARNING: gross hack follows:
# An autotools built package generally needs these scripts, however only
# automake or libtoolize actually install the current versions of them.
# This is a problem in builds that do not use libtool or automake, in the case
# where we -need- the latest version of these scripts. e.g. running a build
# for a package whose autotools are old, on an x86_64 machine, which the old
# config.sub does not support. Work around this by installing them manually
# regardless.
( for ac in `find ${S} -name configure.in -o -name configure.ac`; do
rm -f `dirname $ac`/configure
done )
if [ -e ${S}/configure.in -o -e ${S}/configure.ac ]; then
olddir=`pwd`
cd ${S}
if [ x"${acpaths}" = xdefault ]; then
acpaths=
for i in `find ${S} -maxdepth 2 -name \*.m4|grep -v 'aclocal.m4'| \
grep -v 'acinclude.m4' | sed -e 's,\(.*/\).*$,\1,'|sort -u`; do
acpaths="$acpaths -I $i"
done
else
acpaths="${acpaths}"
fi
AUTOV=`automake --version |head -n 1 |sed "s/.* //;s/\.[0-9]\+$//"`
automake --version
echo "AUTOV is $AUTOV"
install -d ${STAGING_DIR}/${HOST_SYS}/share/aclocal
install -d ${STAGING_DIR}/${HOST_SYS}/share/aclocal-$AUTOV
acpaths="$acpaths -I ${STAGING_DIR}/${HOST_SYS}/share/aclocal-$AUTOV -I ${STAGING_DIR}/${HOST_SYS}/share/aclocal"
# autoreconf is too shy to overwrite aclocal.m4 if it doesn't look
# like it was auto-generated. Work around this by blowing it away
# by hand, unless the package specifically asked not to run aclocal.
if ! echo ${EXTRA_AUTORECONF} | grep -q "aclocal"; then
rm -f aclocal.m4
fi
if [ -e configure.in ]; then
CONFIGURE_AC=configure.in
else
CONFIGURE_AC=configure.ac
fi
if grep "^AM_GLIB_GNU_GETTEXT" $CONFIGURE_AC >/dev/null; then
if grep "sed.*POTFILES" $CONFIGURE_AC >/dev/null; then
: do nothing -- we still have an old unmodified configure.ac
else
oenote Executing glib-gettextize --force --copy
echo "no" | glib-gettextize --force --copy
fi
fi
if grep "^AC_PROG_INTLTOOL" $CONFIGURE_AC >/dev/null; then
oenote Executing intltoolize --copy --force --automake
intltoolize --copy --force --automake
fi
oenote Executing autoreconf --verbose --install --force ${EXTRA_AUTORECONF} $acpaths
mkdir -p m4
autoreconf -Wcross --verbose --install --force ${EXTRA_AUTORECONF} $acpaths || oefatal "autoreconf execution failed."
cd $olddir
fi
;;
esac
if [ -e ${S}/configure ]; then
oe_runconf
else
oenote "nothing to configure"
fi
}
autotools_do_install() {
oe_runmake 'DESTDIR=${D}' install
}
STAGE_TEMP="${WORKDIR}/temp-staging"
autotools_stage_includes() {
if [ "${INHIBIT_AUTO_STAGE_INCLUDES}" != "1" ]
then
rm -rf ${STAGE_TEMP}
mkdir -p ${STAGE_TEMP}
make DESTDIR="${STAGE_TEMP}" install
cp -pPR ${STAGE_TEMP}/${includedir}/* ${STAGING_INCDIR}
rm -rf ${STAGE_TEMP}
fi
}
autotools_stage_all() {
if [ "${INHIBIT_AUTO_STAGE}" != "1" ]
then
rm -rf ${STAGE_TEMP}
mkdir -p ${STAGE_TEMP}
oe_runmake DESTDIR="${STAGE_TEMP}" install
cp -pPR ${STAGE_TEMP}/${includedir}/* ${STAGING_INCDIR}
cp -pPR ${STAGE_TEMP}/${libdir}/* ${STAGING_LIBDIR}
rm -rf ${STAGE_TEMP}
fi
}
EXPORT_FUNCTIONS do_configure do_install

View File

@@ -0,0 +1,822 @@
PATCHES_DIR="${S}"
def base_dep_prepend(d):
import bb;
#
# Ideally this will check a flag so we will operate properly in
# the case where host == build == target, for now we don't work in
# that case though.
#
deps = ""
# INHIBIT_DEFAULT_DEPS doesn't apply to the patch command. Whether or not
# we need that built is the responsibility of the patch function / class, not
# the application.
patchdeps = bb.data.getVar("PATCH_DEPENDS", d, 1)
if patchdeps and not patchdeps in bb.data.getVar("PROVIDES", d, 1):
deps = patchdeps
if not bb.data.getVar('INHIBIT_DEFAULT_DEPS', d):
if (bb.data.getVar('HOST_SYS', d, 1) !=
bb.data.getVar('BUILD_SYS', d, 1)):
deps += " virtual/${TARGET_PREFIX}gcc virtual/libc "
return deps
def base_read_file(filename):
import bb
try:
f = file( filename, "r" )
except IOError, reason:
raise bb.build.FuncFailed("can't read from file '%s' (%s)", (filename,reason))
else:
return f.read().strip()
return None
def base_conditional(variable, checkvalue, truevalue, falsevalue, d):
import bb
if bb.data.getVar(variable,d,1) == checkvalue:
return truevalue
else:
return falsevalue
DEPENDS_prepend="${@base_dep_prepend(d)} "
def base_set_filespath(path, d):
import os, bb
filespath = []
for p in path:
overrides = bb.data.getVar("OVERRIDES", d, 1) or ""
overrides = overrides + ":"
for o in overrides.split(":"):
filespath.append(os.path.join(p, o))
bb.data.setVar("FILESPATH", ":".join(filespath), d)
FILESPATH = "${@base_set_filespath([ "${FILE_DIRNAME}/${PF}", "${FILE_DIRNAME}/${P}", "${FILE_DIRNAME}/${PN}", "${FILE_DIRNAME}/files", "${FILE_DIRNAME}" ], d)}"
def oe_filter(f, str, d):
from re import match
return " ".join(filter(lambda x: match(f, x, 0), str.split()))
def oe_filter_out(f, str, d):
from re import match
return " ".join(filter(lambda x: not match(f, x, 0), str.split()))
die() {
oefatal "$*"
}
oenote() {
echo "NOTE:" "$*"
}
oewarn() {
echo "WARNING:" "$*"
}
oefatal() {
echo "FATAL:" "$*"
exit 1
}
oedebug() {
test $# -ge 2 || {
echo "Usage: oedebug level \"message\""
exit 1
}
test ${OEDEBUG:-0} -ge $1 && {
shift
echo "DEBUG:" $*
}
}
oe_runmake() {
if [ x"$MAKE" = x ]; then MAKE=make; fi
oenote ${MAKE} ${EXTRA_OEMAKE} "$@"
${MAKE} ${EXTRA_OEMAKE} "$@" || die "oe_runmake failed"
}
oe_soinstall() {
# Purpose: Install shared library file and
# create the necessary links
# Example:
#
# oe_
#
#oenote installing shared library $1 to $2
#
libname=`basename $1`
install -m 755 $1 $2/$libname
sonamelink=`${HOST_PREFIX}readelf -d $1 |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
solink=`echo $libname | sed -e 's/\.so\..*/.so/'`
ln -sf $libname $2/$sonamelink
ln -sf $libname $2/$solink
}
oe_libinstall() {
# Purpose: Install a library, in all its forms
# Example
#
# oe_libinstall libltdl ${STAGING_LIBDIR}/
# oe_libinstall -C src/libblah libblah ${D}/${libdir}/
dir=""
libtool=""
silent=""
require_static=""
require_shared=""
staging_install=""
while [ "$#" -gt 0 ]; do
case "$1" in
-C)
shift
dir="$1"
;;
-s)
silent=1
;;
-a)
require_static=1
;;
-so)
require_shared=1
;;
-*)
oefatal "oe_libinstall: unknown option: $1"
;;
*)
break;
;;
esac
shift
done
libname="$1"
shift
destpath="$1"
if [ -z "$destpath" ]; then
oefatal "oe_libinstall: no destination path specified"
fi
if echo "$destpath/" | egrep '^${STAGING_LIBDIR}/' >/dev/null
then
staging_install=1
fi
__runcmd () {
if [ -z "$silent" ]; then
echo >&2 "oe_libinstall: $*"
fi
$*
}
if [ -z "$dir" ]; then
dir=`pwd`
fi
if [ -d "$dir/.libs" ]; then
dir=$dir/.libs
fi
olddir=`pwd`
__runcmd cd $dir
lafile=$libname.la
if [ -f "$lafile" ]; then
# libtool archive
eval `cat $lafile|grep "^library_names="`
libtool=1
else
library_names="$libname.so* $libname.dll.a"
fi
__runcmd install -d $destpath/
dota=$libname.a
if [ -f "$dota" -o -n "$require_static" ]; then
__runcmd install -m 0644 $dota $destpath/
fi
dotlai=$libname.lai
if [ -f "$dotlai" -a -n "$libtool" ]; then
if test -n "$staging_install"
then
# stop libtool using the final directory name for libraries
# in staging:
__runcmd rm -f $destpath/$libname.la
__runcmd sed -e 's/^installed=yes$/installed=no/' $dotlai >$destpath/$libname.la
else
__runcmd install -m 0644 $dotlai $destpath/$libname.la
fi
fi
for name in $library_names; do
files=`eval echo $name`
for f in $files; do
if [ ! -e "$f" ]; then
if [ -n "$libtool" ]; then
oefatal "oe_libinstall: $dir/$f not found."
fi
elif [ -L "$f" ]; then
__runcmd cp -P "$f" $destpath/
elif [ ! -L "$f" ]; then
libfile="$f"
__runcmd install -m 0755 $libfile $destpath/
fi
done
done
if [ -z "$libfile" ]; then
if [ -n "$require_shared" ]; then
oefatal "oe_libinstall: unable to locate shared library"
fi
elif [ -z "$libtool" ]; then
# special case hack for non-libtool .so.#.#.# links
baselibfile=`basename "$libfile"`
if (echo $baselibfile | grep -qE '^lib.*\.so\.[0-9.]*$'); then
sonamelink=`${HOST_PREFIX}readelf -d $libfile |grep 'Library soname:' |sed -e 's/.*\[\(.*\)\].*/\1/'`
solink=`echo $baselibfile | sed -e 's/\.so\..*/.so/'`
if [ -n "$sonamelink" -a x"$baselibfile" != x"$sonamelink" ]; then
__runcmd ln -sf $baselibfile $destpath/$sonamelink
fi
__runcmd ln -sf $baselibfile $destpath/$solink
fi
fi
__runcmd cd "$olddir"
}
oe_machinstall() {
# Purpose: Install machine dependent files, if available
# If not available, check if there is a default
# If no default, just touch the destination
# Example:
# $1 $2 $3 $4
# oe_machinstall -m 0644 fstab ${D}/etc/fstab
#
# TODO: Check argument number?
#
filename=`basename $3`
dirname=`dirname $3`
for o in `echo ${OVERRIDES} | tr ':' ' '`; do
if [ -e $dirname/$o/$filename ]; then
oenote $dirname/$o/$filename present, installing to $4
install $1 $2 $dirname/$o/$filename $4
return
fi
done
# oenote overrides specific file NOT present, trying default=$3...
if [ -e $3 ]; then
oenote $3 present, installing to $4
install $1 $2 $3 $4
else
oenote $3 NOT present, touching empty $4
touch $4
fi
}
addtask showdata
do_showdata[nostamp] = "1"
python do_showdata() {
import sys
# emit variables and shell functions
bb.data.emit_env(sys.__stdout__, d, True)
# emit the metadata which isnt valid shell
for e in d.keys():
if bb.data.getVarFlag(e, 'python', d):
sys.__stdout__.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1)))
}
addtask listtasks
do_listtasks[nostamp] = "1"
python do_listtasks() {
import sys
# emit variables and shell functions
#bb.data.emit_env(sys.__stdout__, d)
# emit the metadata which isnt valid shell
for e in d.keys():
if bb.data.getVarFlag(e, 'task', d):
sys.__stdout__.write("%s\n" % e)
}
addtask clean
do_clean[dirs] = "${TOPDIR}"
do_clean[nostamp] = "1"
do_clean[bbdepcmd] = ""
python base_do_clean() {
"""clear the build and temp directories"""
dir = bb.data.expand("${WORKDIR}", d)
if dir == '//': raise bb.build.FuncFailed("wrong DATADIR")
bb.note("removing " + dir)
os.system('rm -rf ' + dir)
dir = "%s.*" % bb.data.expand(bb.data.getVar('STAMP', d), d)
bb.note("removing " + dir)
os.system('rm -f '+ dir)
}
addtask mrproper
do_mrproper[dirs] = "${TOPDIR}"
do_mrproper[nostamp] = "1"
do_mrproper[bbdepcmd] = ""
python base_do_mrproper() {
"""clear downloaded sources, build and temp directories"""
dir = bb.data.expand("${DL_DIR}", d)
if dir == '/': bb.build.FuncFailed("wrong DATADIR")
bb.debug(2, "removing " + dir)
os.system('rm -rf ' + dir)
bb.build.exec_task('do_clean', d)
}
addtask fetch
do_fetch[dirs] = "${DL_DIR}"
do_fetch[nostamp] = "1"
python base_do_fetch() {
import sys
localdata = bb.data.createCopy(d)
bb.data.update_data(localdata)
src_uri = bb.data.getVar('SRC_URI', localdata, 1)
if not src_uri:
return 1
try:
bb.fetch.init(src_uri.split(),d)
except bb.fetch.NoMethodError:
(type, value, traceback) = sys.exc_info()
raise bb.build.FuncFailed("No method: %s" % value)
try:
bb.fetch.go(localdata)
except bb.fetch.MissingParameterError:
(type, value, traceback) = sys.exc_info()
raise bb.build.FuncFailed("Missing parameters: %s" % value)
except bb.fetch.FetchError:
(type, value, traceback) = sys.exc_info()
raise bb.build.FuncFailed("Fetch failed: %s" % value)
}
def oe_unpack_file(file, data, url = None):
import bb, os
if not url:
url = "file://%s" % file
dots = file.split(".")
if dots[-1] in ['gz', 'bz2', 'Z']:
efile = os.path.join(bb.data.getVar('WORKDIR', data, 1),os.path.basename('.'.join(dots[0:-1])))
else:
efile = file
cmd = None
if file.endswith('.tar'):
cmd = 'tar x --no-same-owner -f %s' % file
elif file.endswith('.tgz') or file.endswith('.tar.gz'):
cmd = 'tar xz --no-same-owner -f %s' % file
elif file.endswith('.tbz') or file.endswith('.tar.bz2'):
cmd = 'bzip2 -dc %s | tar x --no-same-owner -f -' % file
elif file.endswith('.gz') or file.endswith('.Z') or file.endswith('.z'):
cmd = 'gzip -dc %s > %s' % (file, efile)
elif file.endswith('.bz2'):
cmd = 'bzip2 -dc %s > %s' % (file, efile)
elif file.endswith('.zip'):
cmd = 'unzip -q %s' % file
elif os.path.isdir(file):
filesdir = os.path.realpath(bb.data.getVar("FILESDIR", data, 1))
destdir = "."
if file[0:len(filesdir)] == filesdir:
destdir = file[len(filesdir):file.rfind('/')]
destdir = destdir.strip('/')
if len(destdir) < 1:
destdir = "."
elif not os.access("%s/%s" % (os.getcwd(), destdir), os.F_OK):
os.makedirs("%s/%s" % (os.getcwd(), destdir))
cmd = 'cp -pPR %s %s/%s/' % (file, os.getcwd(), destdir)
else:
(type, host, path, user, pswd, parm) = bb.decodeurl(url)
if not 'patch' in parm:
# The "destdir" handling was specifically done for FILESPATH
# items. So, only do so for file:// entries.
if type == "file":
destdir = bb.decodeurl(url)[1] or "."
else:
destdir = "."
bb.mkdirhier("%s/%s" % (os.getcwd(), destdir))
cmd = 'cp %s %s/%s/' % (file, os.getcwd(), destdir)
if not cmd:
return True
cmd = "PATH=\"%s\" %s" % (bb.data.getVar('PATH', data, 1), cmd)
bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
ret = os.system(cmd)
return ret == 0
addtask unpack after do_fetch
do_unpack[dirs] = "${WORKDIR}"
python base_do_unpack() {
import re, os
localdata = bb.data.createCopy(d)
bb.data.update_data(localdata)
src_uri = bb.data.getVar('SRC_URI', localdata)
if not src_uri:
return
src_uri = bb.data.expand(src_uri, localdata)
for url in src_uri.split():
try:
local = bb.data.expand(bb.fetch.localpath(url, localdata), localdata)
except bb.MalformedUrl, e:
raise FuncFailed('Unable to generate local path for malformed uri: %s' % e)
# dont need any parameters for extraction, strip them off
local = re.sub(';.*$', '', local)
local = os.path.realpath(local)
ret = oe_unpack_file(local, localdata, url)
if not ret:
raise bb.build.FuncFailed()
}
addtask patch after do_unpack
do_patch[dirs] = "${WORKDIR}"
python base_do_patch() {
import re
import bb.fetch
src_uri = (bb.data.getVar('SRC_URI', d, 1) or '').split()
if not src_uri:
return
patchcleancmd = bb.data.getVar('PATCHCLEANCMD', d, 1)
if patchcleancmd:
bb.data.setVar("do_patchcleancmd", patchcleancmd, d)
bb.data.setVarFlag("do_patchcleancmd", "func", 1, d)
bb.build.exec_func("do_patchcleancmd", d)
workdir = bb.data.getVar('WORKDIR', d, 1)
for url in src_uri:
(type, host, path, user, pswd, parm) = bb.decodeurl(url)
if not "patch" in parm:
continue
bb.fetch.init([url], d)
url = bb.encodeurl((type, host, path, user, pswd, []))
local = os.path.join('/', bb.fetch.localpath(url, d))
# did it need to be unpacked?
dots = os.path.basename(local).split(".")
if dots[-1] in ['gz', 'bz2', 'Z']:
unpacked = os.path.join(bb.data.getVar('WORKDIR', d),'.'.join(dots[0:-1]))
else:
unpacked = local
unpacked = bb.data.expand(unpacked, d)
if "pnum" in parm:
pnum = parm["pnum"]
else:
pnum = "1"
if "pname" in parm:
pname = parm["pname"]
else:
pname = os.path.basename(unpacked)
bb.note("Applying patch '%s'" % pname)
bb.data.setVar("do_patchcmd", bb.data.getVar("PATCHCMD", d, 1) % (pnum, pname, unpacked), d)
bb.data.setVarFlag("do_patchcmd", "func", 1, d)
bb.data.setVarFlag("do_patchcmd", "dirs", "${WORKDIR} ${S}", d)
bb.build.exec_func("do_patchcmd", d)
}
addhandler base_eventhandler
python base_eventhandler() {
from bb import note, error, data
from bb.event import Handled, NotHandled, getName
import os
messages = {}
messages["Completed"] = "completed"
messages["Succeeded"] = "completed"
messages["Started"] = "started"
messages["Failed"] = "failed"
name = getName(e)
msg = ""
if name.startswith("Pkg"):
msg += "package %s: " % data.getVar("P", e.data, 1)
msg += messages.get(name[3:]) or name[3:]
elif name.startswith("Task"):
msg += "package %s: task %s: " % (data.getVar("PF", e.data, 1), e.task)
msg += messages.get(name[4:]) or name[4:]
elif name.startswith("Build"):
msg += "build %s: " % e.name
msg += messages.get(name[5:]) or name[5:]
elif name == "UnsatisfiedDep":
msg += "package %s: dependency %s %s" % (e.pkg, e.dep, name[:-3].lower())
note(msg)
if name.startswith("BuildStarted"):
bb.data.setVar( 'BB_VERSION', bb.__version__, e.data )
path_to_bbfiles = bb.data.getVar( 'BBFILES', e.data, 1 )
path_to_packages = path_to_bbfiles[:path_to_bbfiles.index( "packages" )]
monotone_revision = "<unknown>"
try:
monotone_revision = file( "%s/MT/revision" % path_to_packages ).read().strip()
except IOError:
pass
bb.data.setVar( 'OE_REVISION', monotone_revision, e.data )
statusvars = ['BB_VERSION', 'OE_REVISION', 'TARGET_ARCH', 'TARGET_OS', 'MACHINE', 'DISTRO', 'TARGET_FPU']
statuslines = ["%-13s = \"%s\"" % (i, bb.data.getVar(i, e.data, 1) or '') for i in statusvars]
statusmsg = "\nOE Build Configuration:\n%s\n" % '\n'.join(statuslines)
print statusmsg
needed_vars = [ "TARGET_ARCH", "TARGET_OS" ]
pesteruser = []
for v in needed_vars:
val = bb.data.getVar(v, e.data, 1)
if not val or val == 'INVALID':
pesteruser.append(v)
if pesteruser:
bb.fatal('The following variable(s) were not set: %s\nPlease set them directly, or choose a MACHINE or DISTRO that sets them.' % ', '.join(pesteruser))
if not data in e.__dict__:
return NotHandled
log = data.getVar("EVENTLOG", e.data, 1)
if log:
logfile = file(log, "a")
logfile.write("%s\n" % msg)
logfile.close()
return NotHandled
}
addtask configure after do_unpack do_patch
do_configure[dirs] = "${S} ${B}"
do_configure[bbdepcmd] = "do_populate_staging"
base_do_configure() {
:
}
addtask compile after do_configure
do_compile[dirs] = "${S} ${B}"
do_compile[bbdepcmd] = "do_populate_staging"
base_do_compile() {
if [ -e Makefile -o -e makefile ]; then
oe_runmake || die "make failed"
else
oenote "nothing to compile"
fi
}
addtask stage after do_compile
base_do_stage () {
:
}
do_populate_staging[dirs] = "${STAGING_DIR}/${TARGET_SYS}/bin ${STAGING_DIR}/${TARGET_SYS}/lib \
${STAGING_DIR}/${TARGET_SYS}/include \
${STAGING_DIR}/${BUILD_SYS}/bin ${STAGING_DIR}/${BUILD_SYS}/lib \
${STAGING_DIR}/${BUILD_SYS}/include \
${STAGING_DATADIR} \
${S} ${B}"
addtask populate_staging after do_compile
#python do_populate_staging () {
# if not bb.data.getVar('manifest', d):
# bb.build.exec_func('do_emit_manifest', d)
# if bb.data.getVar('do_stage', d):
# bb.build.exec_func('do_stage', d)
# else:
# bb.build.exec_func('manifest_do_populate_staging', d)
#}
python do_populate_staging () {
if bb.data.getVar('manifest_do_populate_staging', d):
bb.build.exec_func('manifest_do_populate_staging', d)
else:
bb.build.exec_func('do_stage', d)
}
#addtask install
addtask install after do_compile
do_install[dirs] = "${S} ${B}"
base_do_install() {
:
}
#addtask populate_pkgs after do_compile
#python do_populate_pkgs () {
# if not bb.data.getVar('manifest', d):
# bb.build.exec_func('do_emit_manifest', d)
# bb.build.exec_func('manifest_do_populate_pkgs', d)
# bb.build.exec_func('package_do_shlibs', d)
#}
base_do_package() {
:
}
addtask build after do_populate_staging
do_build = ""
do_build[func] = "1"
# Functions that update metadata based on files outputted
# during the build process.
SHLIBS = ""
RDEPENDS_prepend = " ${SHLIBS}"
python read_manifest () {
import sys
mfn = bb.data.getVar("MANIFEST", d, 1)
if os.access(mfn, os.R_OK):
# we have a manifest, so emit do_stage and do_populate_pkgs,
# and stuff some additional bits of data into the metadata store
mfile = file(mfn, "r")
manifest = bb.manifest.parse(mfile, d)
if not manifest:
return
bb.data.setVar('manifest', manifest, d)
}
python parse_manifest () {
manifest = bb.data.getVar("manifest", d)
if not manifest:
return
for func in ("do_populate_staging", "do_populate_pkgs"):
value = bb.manifest.emit(func, manifest, d)
if value:
bb.data.setVar("manifest_" + func, value, d)
bb.data.delVarFlag("manifest_" + func, "python", d)
bb.data.delVarFlag("manifest_" + func, "fakeroot", d)
bb.data.setVarFlag("manifest_" + func, "func", 1, d)
packages = []
for l in manifest:
if "pkg" in l and l["pkg"] is not None:
packages.append(l["pkg"])
bb.data.setVar("PACKAGES", " ".join(packages), d)
}
def explode_deps(s):
r = []
l = s.split()
flag = False
for i in l:
if i[0] == '(':
flag = True
j = []
if flag:
j.append(i)
if i.endswith(')'):
flag = False
r[-1] += ' ' + ' '.join(j)
else:
r.append(i)
return r
python read_shlibdeps () {
packages = (bb.data.getVar('PACKAGES', d, 1) or "").split()
for pkg in packages:
rdepends = explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 0) or bb.data.getVar('RDEPENDS', d, 0) or "")
shlibsfile = bb.data.expand("${WORKDIR}/install/" + pkg + ".shlibdeps", d)
if os.access(shlibsfile, os.R_OK):
fd = file(shlibsfile)
lines = fd.readlines()
fd.close()
for l in lines:
rdepends.append(l.rstrip())
pcfile = bb.data.expand("${WORKDIR}/install/" + pkg + ".pcdeps", d)
if os.access(pcfile, os.R_OK):
fd = file(pcfile)
lines = fd.readlines()
fd.close()
for l in lines:
rdepends.append(l.rstrip())
bb.data.setVar('RDEPENDS_' + pkg, " " + " ".join(rdepends), d)
}
python read_subpackage_metadata () {
import re
def decode(str):
import codecs
c = codecs.getdecoder("string_escape")
return c(str)[0]
data_file = bb.data.expand("${WORKDIR}/install/${PN}.package", d)
if os.access(data_file, os.R_OK):
f = file(data_file, 'r')
lines = f.readlines()
f.close()
r = re.compile("([^:]+):\s*(.*)")
for l in lines:
m = r.match(l)
if m:
bb.data.setVar(m.group(1), decode(m.group(2)), d)
}
python __anonymous () {
import exceptions
need_host = bb.data.getVar('COMPATIBLE_HOST', d, 1)
if need_host:
import re
this_host = bb.data.getVar('HOST_SYS', d, 1)
if not re.match(need_host, this_host):
raise bb.parse.SkipPackage("incompatible with host %s" % this_host)
pn = bb.data.getVar('PN', d, 1)
cvsdate = bb.data.getVar('CVSDATE_%s' % pn, d, 1)
if cvsdate != None:
bb.data.setVar('CVSDATE', cvsdate, d)
use_nls = bb.data.getVar('USE_NLS_%s' % pn, d, 1)
if use_nls != None:
bb.data.setVar('USE_NLS', use_nls, d)
try:
bb.build.exec_func('read_manifest', d)
bb.build.exec_func('parse_manifest', d)
except exceptions.KeyboardInterrupt:
raise
except Exception, e:
bb.error("anonymous function: %s" % e)
pass
}
python () {
import bb, os
mach_arch = bb.data.getVar('MACHINE_ARCH', d, 1)
old_arch = bb.data.getVar('PACKAGE_ARCH', d, 1)
if (old_arch == mach_arch):
# Nothing to do
return
if (bb.data.getVar('SRC_URI_OVERRIDES_PACKAGE_ARCH', d, 1) == '0'):
return
paths = []
for p in [ "${FILE_DIRNAME}/${PF}", "${FILE_DIRNAME}/${P}", "${FILE_DIRNAME}/${PN}", "${FILE_DIRNAME}/files", "${FILE_DIRNAME}" ]:
paths.append(bb.data.expand(os.path.join(p, mach_arch), d))
for s in bb.data.getVar('SRC_URI', d, 1).split():
local = bb.data.expand(bb.fetch.localpath(s, d), d)
for mp in paths:
if local.startswith(mp):
# bb.note("overriding PACKAGE_ARCH from %s to %s" % (old_arch, mach_arch))
bb.data.setVar('PACKAGE_ARCH', mach_arch, d)
return
}
addtask emit_manifest
python do_emit_manifest () {
# FIXME: emit a manifest here
# 1) adjust PATH to hit the wrapper scripts
wrappers = bb.which(bb.data.getVar("BBPATH", d, 1), 'build/install', 0)
path = (bb.data.getVar('PATH', d, 1) or '').split(':')
path.insert(0, os.path.dirname(wrappers))
bb.data.setVar('PATH', ':'.join(path), d)
# 2) exec_func("do_install", d)
bb.build.exec_func('do_install', d)
# 3) read in data collected by the wrappers
bb.build.exec_func('read_manifest', d)
# 4) mangle the manifest we just generated, get paths back into
# our variable form
# 5) write it back out
# 6) re-parse it to ensure the generated functions are proper
bb.build.exec_func('parse_manifest', d)
}
EXPORT_FUNCTIONS do_clean do_mrproper do_fetch do_unpack do_configure do_compile do_install do_package do_patch do_populate_pkgs do_stage
MIRRORS[func] = "0"
MIRRORS () {
${DEBIAN_MIRROR}/main http://snapshot.debian.net/archive/pool
${DEBIAN_MIRROR} ftp://ftp.de.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.au.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.cl.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.hr.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.fi.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.hk.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.hu.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.ie.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.it.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.jp.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.no.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.pl.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.ro.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.si.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.es.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.se.debian.org/debian/pool
${DEBIAN_MIRROR} ftp://ftp.tr.debian.org/debian/pool
${GNU_MIRROR} ftp://mirrors.kernel.org/gnu
${GNU_MIRROR} ftp://ftp.matrix.com.br/pub/gnu
${GNU_MIRROR} ftp://ftp.cs.ubc.ca/mirror2/gnu
${GNU_MIRROR} ftp://sunsite.ust.hk/pub/gnu
${GNU_MIRROR} ftp://ftp.ayamura.org/pub/gnu
ftp://ftp.kernel.org/pub http://www.kernel.org/pub
ftp://ftp.kernel.org/pub ftp://ftp.us.kernel.org/pub
ftp://ftp.kernel.org/pub ftp://ftp.uk.kernel.org/pub
ftp://ftp.kernel.org/pub ftp://ftp.hk.kernel.org/pub
ftp://ftp.kernel.org/pub ftp://ftp.au.kernel.org/pub
ftp://ftp.kernel.org/pub ftp://ftp.jp.kernel.org/pub
ftp://.*/.*/ http://www.oesources.org/source/current/
http://.*/.*/ http://www.oesources.org/source/current/
}

View File

@@ -0,0 +1,20 @@
inherit base package rpm_core
SPECFILE="${RPMBUILDPATH}/SPECS/${PN}.spec"
base_srpm_do_unpack() {
test -e ${SRPMFILE} || die "Source rpm \"${SRPMFILE}\"does not exist"
if ! test -e ${SPECFILE}; then
${RPM} -i ${SRPMFILE}
fi
test -e ${SPECFILE} || die "Spec file \"${SPECFILE}\" does not exist"
${RPMBUILD} -bp ${SPECFILE}
}
base_srpm_do_compile() {
${RPMBUILD} -bc ${SPECFILE}
}
base_srpm_do_install() {
${RPMBUILD} -bi ${SPECFILE}
}

View File

@@ -0,0 +1,36 @@
inherit base
# The namespaces can clash here hence the two step replace
def get_binconfig_mangle(d):
import bb.data
s = "-e ''"
if not bb.data.inherits_class('native', d):
s += " -e 's:=${libdir}:=OELIBDIR:;'"
s += " -e 's:=${includedir}:=OEINCDIR:;'"
s += " -e 's:=${datadir}:=OEDATADIR:'"
s += " -e 's:=${prefix}:=OEPREFIX:'"
s += " -e 's:=${exec_prefix}:=OEEXECPREFIX:'"
s += " -e 's:-L${libdir}:-LOELIBDIR:;'"
s += " -e 's:-I${includedir}:-IOEINCDIR:;'"
s += " -e 's:OELIBDIR:${STAGING_LIBDIR}:;'"
s += " -e 's:OEINCDIR:${STAGING_INCDIR}:;'"
s += " -e 's:OEDATADIR:${STAGING_DATADIR}:'"
s += " -e 's:OEPREFIX:${STAGING_LIBDIR}/..:'"
s += " -e 's:OEEXECPREFIX:${STAGING_LIBDIR}/..:'"
return s
# Native package configurations go in ${BINDIR}/<name>-config-native to prevent a collision with cross packages
def is_native(d):
import bb.data
return ["","-native"][bb.data.inherits_class('native', d)]
BINCONFIG_GLOB ?= "*-config"
do_stage_append() {
for config in `find ${S} -name '${BINCONFIG_GLOB}'`; do
configname=`basename $config`${@is_native(d)}
install -d ${STAGING_BINDIR}
cat $config | sed ${@get_binconfig_mangle(d)} > ${STAGING_BINDIR}/$configname
chmod u+x ${STAGING_BINDIR}/$configname
done
}

View File

@@ -0,0 +1,11 @@
# Make ccache use a TMPDIR specific ccache directory if using the crosscompiler,
# since it isn't likely to be useful with any other toolchain than the one we just
# built, and would otherwise push more useful things out of the default cache.
CCACHE_DIR_TARGET = "${TMPDIR}/ccache"
python () {
if not bb.data.inherits_class('native', d) and not bb.data.inherits_class('cross', d):
bb.data.setVar('CCACHE_DIR', '${CCACHE_DIR_TARGET}', d)
bb.data.setVarFlag('CCACHE_DIR', 'export', '1', d)
}

View File

@@ -0,0 +1,21 @@
python () {
if bb.data.getVar('PN', d, 1) in ['ccdv-native']:
if not bb.data.getVar('INHIBIT_DEFAULT_DEPS', d, 1):
bb.data.setVar("DEPENDS", '%s %s' % ("ccdv-native", bb.data.getVar("DEPENDS", d, 1) or ""), d)
bb.data.setVar("CC", '%s %s' % ("ccdv", bb.data.getVar("CC", d, 1) or ""), d)
bb.data.setVar("BUILD_CC", '%s %s' % ("ccdv", bb.data.getVar("BUILD_CC", d, 1) or ""), d)
bb.data.setVar("CCLD", '%s %s' % ("ccdv", bb.data.getVar("CCLD", d, 1) or ""), d)
}
def quiet_libtool(bb,d):
deps = (bb.data.getVar('DEPENDS', d, 1) or "").split()
if 'libtool-cross' in deps:
return "'LIBTOOL=${STAGING_BINDIR}/${HOST_SYS}-libtool --silent'"
elif 'libtool-native' in deps:
return "'LIBTOOL=${B}/${HOST_SYS}-libtool --silent'"
else:
return ""
CCDV = "ccdv"
EXTRA_OEMAKE_append = " ${@quiet_libtool(bb,d)}"
MAKE += "-s"

View File

@@ -0,0 +1,8 @@
cml1_do_configure() {
set -e
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake oldconfig
}
EXPORT_FUNCTIONS do_configure
addtask configure after do_unpack do_patch before do_compile

View File

@@ -0,0 +1,20 @@
FILES_${PN} += '${libdir}/perl5'
cpan_do_configure () {
perl Makefile.PL
if [ "${BUILD_SYS}" != "${HOST_SYS}" ]; then
. ${STAGING_DIR}/${TARGET_SYS}/perl/config.sh
sed -e "s:\(SITELIBEXP = \).*:\1${sitelibexp}:; s:\(SITEARCHEXP = \).*:\1${sitearchexp}:; s:\(INSTALLVENDORLIB = \).*:\1${D}${libdir}/perl5:; s:\(INSTALLVENDORARCH = \).*:\1${D}${libdir}/perl5:" < Makefile > Makefile.new
mv Makefile.new Makefile
fi
}
cpan_do_compile () {
oe_runmake PASTHRU_INC="${CFLAGS}"
}
cpan_do_install () {
oe_runmake install_vendor
}
EXPORT_FUNCTIONS do_configure do_compile do_install

View File

@@ -0,0 +1,54 @@
# Cross packages are built indirectly via dependency,
# no need for them to be a direct target of 'world'
EXCLUDE_FROM_WORLD = "1"
PACKAGES = ""
HOST_ARCH = "${BUILD_ARCH}"
HOST_VENDOR = "${BUILD_VENDOR}"
HOST_OS = "${BUILD_OS}"
HOST_PREFIX = "${BUILD_PREFIX}"
HOST_CC_ARCH = "${BUILD_CC_ARCH}"
CPPFLAGS = "${BUILD_CPPFLAGS}"
CFLAGS = "${BUILD_CFLAGS}"
CXXFLAGS = "${BUILD_CFLAGS}"
LDFLAGS = "${BUILD_LDFLAGS}"
# Overrides for paths
# Path prefixes
base_prefix = "${exec_prefix}"
prefix = "${CROSS_DIR}"
exec_prefix = "${prefix}"
# Base paths
base_bindir = "${base_prefix}/bin"
base_sbindir = "${base_prefix}/bin"
base_libdir = "${base_prefix}/lib"
# Architecture independent paths
datadir = "${prefix}/share"
sysconfdir = "${prefix}/etc"
sharedstatedir = "${prefix}/com"
localstatedir = "${prefix}/var"
infodir = "${datadir}/info"
mandir = "${datadir}/man"
docdir = "${datadir}/doc"
servicedir = "${prefix}/srv"
# Architecture dependent paths
bindir = "${exec_prefix}/bin"
sbindir = "${exec_prefix}/bin"
libexecdir = "${exec_prefix}/libexec"
libdir = "${exec_prefix}/lib"
includedir = "${exec_prefix}/include"
oldincludedir = "${exec_prefix}/include"
do_stage () {
oe_runmake install
}
do_install () {
:
}

View File

@@ -0,0 +1,93 @@
python debian_package_name_hook () {
import glob, copy, stat, errno, re
workdir = bb.data.getVar('WORKDIR', d, 1)
packages = bb.data.getVar('PACKAGES', d, 1)
def socrunch(s):
s = s.lower().replace('_', '-')
m = re.match("^(.*)(.)\.so\.(.*)$", s)
if m is None:
return None
if m.group(2) in '0123456789':
bin = '%s%s-%s' % (m.group(1), m.group(2), m.group(3))
else:
bin = m.group(1) + m.group(2) + m.group(3)
dev = m.group(1) + m.group(2)
return (bin, dev)
def isexec(path):
try:
s = os.stat(path)
except (os.error, AttributeError):
return 0
return (s[stat.ST_MODE] & stat.S_IEXEC)
def auto_libname(packages, orig_pkg):
bin_re = re.compile(".*/s?bin$")
lib_re = re.compile(".*/lib$")
so_re = re.compile("lib.*\.so")
sonames = []
has_bins = 0
has_libs = 0
pkg_dir = os.path.join(workdir, "install", orig_pkg)
for root, dirs, files in os.walk(pkg_dir):
if bin_re.match(root) and files:
has_bins = 1
if lib_re.match(root) and files:
has_libs = 1
for f in files:
if so_re.match(f):
fp = os.path.join(root, f)
cmd = (bb.data.getVar('BUILD_PREFIX', d, 1) or "") + "objdump -p " + fp + " 2>/dev/null"
fd = os.popen(cmd)
lines = fd.readlines()
fd.close()
for l in lines:
m = re.match("\s+SONAME\s+([^\s]*)", l)
if m and not m.group(1) in sonames:
sonames.append(m.group(1))
bb.debug(1, 'LIBNAMES: pkg %s libs %d bins %d sonames %s' % (orig_pkg, has_libs, has_bins, sonames))
soname = None
if len(sonames) == 1:
soname = sonames[0]
elif len(sonames) > 1:
lead = bb.data.getVar('LEAD_SONAME', d, 1)
if lead:
r = re.compile(lead)
filtered = []
for s in sonames:
if r.match(s):
filtered.append(s)
if len(filtered) == 1:
soname = filtered[0]
elif len(filtered) > 1:
bb.note("Multiple matches (%s) for LEAD_SONAME '%s'" % (", ".join(filtered), lead))
else:
bb.note("Multiple libraries (%s) found, but LEAD_SONAME '%s' doesn't match any of them" % (", ".join(sonames), lead))
else:
bb.note("Multiple libraries (%s) found and LEAD_SONAME not defined" % ", ".join(sonames))
if has_libs and not has_bins and soname:
soname_result = socrunch(soname)
if soname_result:
(pkgname, devname) = soname_result
for pkg in packages.split():
if (bb.data.getVar('PKG_' + pkg, d)):
continue
if pkg == orig_pkg:
newpkg = pkgname
else:
newpkg = pkg.replace(orig_pkg, devname, 1)
if newpkg != pkg:
bb.data.setVar('PKG_' + pkg, newpkg, d)
for pkg in (bb.data.getVar('AUTO_LIBNAME_PKGS', d, 1) or "").split():
auto_libname(packages, pkg)
}
EXPORT_FUNCTIONS package_name_hook
DEBIAN_NAMES = 1

View File

@@ -0,0 +1,14 @@
EXTRA_OEMAKE = ""
DEPENDS += "${@["python-native python", ""][(bb.data.getVar('PACKAGES', d, 1) == '')]}"
RDEPENDS += "python-core"
def python_dir(d):
import os, bb
staging_incdir = bb.data.getVar( "STAGING_INCDIR", d, 1 )
if os.path.exists( "%s/python2.3" % staging_incdir ): return "python2.3"
if os.path.exists( "%s/python2.4" % staging_incdir ): return "python2.4"
raise "No Python in STAGING_INCDIR. Forgot to build python-native ?"
PYTHON_DIR = "${@python_dir(d)}"
FILES_${PN} = "${bindir} ${libdir} ${libdir}/${PYTHON_DIR}"

View File

@@ -0,0 +1,15 @@
inherit distutils-base
distutils_do_compile() {
BUILD_SYS=${BUILD_SYS} HOST_SYS=${HOST_SYS} \
${STAGING_BINDIR}/python setup.py build || \
oefatal "python setup.py build execution failed."
}
distutils_do_install() {
BUILD_SYS=${BUILD_SYS} HOST_SYS=${HOST_SYS} \
${STAGING_BINDIR}/python setup.py install --prefix=${D}/${prefix} --install-data=${D}/${datadir} || \
oefatal "python setup.py install execution failed."
}
EXPORT_FUNCTIONS do_compile do_install

View File

@@ -0,0 +1,81 @@
MAINTAINER = "Justin Patrin <papercrane@reversefold.com>"
HOMEPAGE = "http://www.enlightenment.org"
SECTION = "e/libs"
SRCNAME = "${@bb.data.getVar('PN', d, 1).replace('-native', '')}"
SRC_URI = "http://enlightenment.freedesktop.org/files/${SRCNAME}-${PV}.tar.gz"
S = "${WORKDIR}/${SRCNAME}-${PV}"
inherit autotools pkgconfig binconfig
do_prepsources () {
make clean distclean || true
}
addtask prepsources after do_fetch before do_unpack
INHIBIT_AUTO_STAGE_INCLUDES = "1"
INHIBIT_NATIVE_STAGE_INSTALL = "1"
libdirectory = "src/lib"
libraries = "lib${SRCNAME}"
headers = "${@bb.data.getVar('SRCNAME',d,1).capitalize()}.h"
def binconfig_suffix(d):
import bb
return ["","-native"][bb.data.inherits_class('native', d)]
export CURL_CONFIG = "${STAGING_BINDIR}/curl-config${@binconfig_suffix(d)}"
export EDB_CONFIG = "${STAGING_BINDIR}/edb-config${@binconfig_suffix(d)}"
export EET_CONFIG = "${STAGING_BINDIR}/eet-config${@binconfig_suffix(d)}"
export EVAS_CONFIG = "${STAGING_BINDIR}/evas-config${@binconfig_suffix(d)}"
export ECORE_CONFIG = "${STAGING_BINDIR}/ecore-config${@binconfig_suffix(d)}"
export EMBRYO_CONFIG = "${STAGING_BINDIR}/embryo-config${@binconfig_suffix(d)}"
export ENGRAVE_CONFIG = "${STAGING_BINDIR}/engrave-config${@binconfig_suffix(d)}"
export ENLIGHTENMENT_CONFIG = "${STAGING_BINDIR}/enlightenment-config${@binconfig_suffix(d)}"
export EPSILON_CONFIG = "${STAGING_BINDIR}/epsilon-config${@binconfig_suffix(d)}"
export EPEG_CONFIG = "${STAGING_BINDIR}/epeg-config${@binconfig_suffix(d)}"
export ESMART_CONFIG = "${STAGING_BINDIR}/esmart-config${@binconfig_suffix(d)}"
export FREETYPE_CONFIG = "${STAGING_BINDIR}/freetype-config${@binconfig_suffix(d)}"
export IMLIB2_CONFIG = "${STAGING_BINDIR}/imlib2-config${@binconfig_suffix(d)}"
do_compile_prepend() {
find ${S} -name Makefile | xargs sed -i 's:/usr/include:${STAGING_INCDIR}:'
find ${S} -name Makefile | xargs sed -i 's:/usr/X11R6/include:${STAGING_INCDIR}:'
}
do_stage_append () {
for i in ${libraries}
do
oe_libinstall -C ${libdirectory} $i ${STAGING_LIBDIR}
done
for i in ${headers}
do
install -m 0644 ${libdirectory}/$i ${STAGING_INCDIR}
done
# Install binaries automatically for native builds
if [ "${@binconfig_suffix(d)}" = "-native" ]
then
# Most EFL binaries start with the package name
for i in src/bin/${SRCNAME}*
do
if [ -x $i -a -f $i ]
then
# Don't install anything with an extension (.so, etc)
if echo $i | grep -v \\.
then
${HOST_SYS}-libtool --mode=install install -m 0755 $i ${STAGING_BINDIR}
fi
fi
done
fi
}
PACKAGES = "${SRCNAME} ${SRCNAME}-themes ${SRCNAME}-dev ${SRCNAME}-examples"
FILES_${SRCNAME} = "${libdir}/lib*.so*"
FILES_${SRCNAME}-themes = "${datadir}/${SRCNAME}/themes ${datadir}/${SRCNAME}/data ${datadir}/${SRCNAME}/fonts ${datadir}/${SRCNAME}/pointers ${datadir}/${SRCNAME}/images ${datadir}/${SRCNAME}/users ${datadir}/${SRCNAME}/images ${datadir}/${SRCNAME}/styles"
FILES_${SRCNAME}-dev += "${bindir}/${SRCNAME}-config ${libdir}/pkgconfig ${libdir}/lib*.?a ${datadir}/${SRCNAME}/include"
FILES_${SRCNAME}-examples = "${bindir} ${datadir}"

View File

@@ -0,0 +1,5 @@
# gcc-3.4 blows up in gtktext with -frename-registers on arm-linux
python () {
cflags = (bb.data.getVar('CFLAGS', d, 1) or '').replace('-frename-registers', '')
bb.data.setVar('CFLAGS', cflags, d)
}

View File

@@ -0,0 +1,57 @@
gconf_postinst() {
if [ "$1" = configure ]; then
if [ "x$D" != "x" ]; then
exit 1
fi
SCHEMA_LOCATION=/etc/gconf/schemas
for SCHEMA in ${SCHEMA_FILES}; do
if [ -e $SCHEMA_LOCATION/$SCHEMA ]; then
HOME=/root GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \
gconftool-2 \
--makefile-install-rule $SCHEMA_LOCATION/$SCHEMA > /dev/null
fi
done
fi
}
gconf_prerm() {
if [ "$1" = remove ] || [ "$1" = upgrade ]; then
SCHEMA_LOCATION=/etc/gconf/schemas
for SCHEMA in ${SCHEMA_FILES}; do
if [ -e $SCHEMA_LOCATION/$SCHEMA ]; then
HOME=/root GCONF_CONFIG_SOURCE=`gconftool-2 --get-default-source` \
gconftool-2 \
--makefile-uninstall-rule $SCHEMA_LOCATION/$SCHEMA > /dev/null
fi
done
fi
}
python populate_packages_append () {
import os.path, re
packages = bb.data.getVar('PACKAGES', d, 1).split()
workdir = bb.data.getVar('WORKDIR', d, 1)
for pkg in packages:
schema_dir = '%s/install/%s/etc/gconf/schemas' % (workdir, pkg)
schemas = []
schema_re = re.compile(".*\.schemas$")
if os.path.exists(schema_dir):
for f in os.listdir(schema_dir):
if schema_re.match(f):
schemas.append(f)
if schemas != []:
bb.note("adding gconf postinst and prerm scripts to %s" % pkg)
bb.data.setVar('SCHEMA_FILES', " ".join(schemas), d)
postinst = bb.data.getVar('pkg_postinst_%s' % pkg, d, 1) or bb.data.getVar('pkg_postinst', d, 1)
if not postinst:
postinst = '#!/bin/sh\n'
postinst += bb.data.getVar('gconf_postinst', d, 1)
bb.data.setVar('pkg_postinst_%s' % pkg, postinst, d)
prerm = bb.data.getVar('pkg_prerm_%s' % pkg, d, 1) or bb.data.getVar('pkg_prerm', d, 1)
if not prerm:
prerm = '#!/bin/sh\n'
prerm += bb.data.getVar('gconf_prerm', d, 1)
bb.data.setVar('pkg_prerm_%s' % pkg, prerm, d)
}

View File

@@ -0,0 +1,12 @@
python () {
# Remove the NLS bits if USE_NLS is no.
if bb.data.getVar('USE_NLS', d, 1) == 'no':
cfg = oe_filter_out('^--(dis|en)able-nls$', bb.data.getVar('EXTRA_OECONF', d, 1) or "", d)
cfg += " --disable-nls"
depends = bb.data.getVar('DEPENDS', d, 1) or ""
bb.data.setVar('DEPENDS', oe_filter_out('^(virtual/libiconv|virtual/libintl)$', depends, d), d)
bb.data.setVar('EXTRA_OECONF', cfg, d)
}
DEPENDS =+ "gettext-native"
EXTRA_OECONF += "--enable-nls"

View File

@@ -0,0 +1,20 @@
def gnome_verdir(v):
import re
m = re.match("([0-9]+)\.([0-9]+)\..*", v)
return "%s.%s" % (m.group(1), m.group(2))
SECTION ?= "x11/gnome"
SRC_URI = "${GNOME_MIRROR}/${PN}/${@gnome_verdir("${PV}")}/${PN}-${PV}.tar.bz2"
DEPENDS += "gnome-common"
FILES_${PN} += "${datadir}/application-registry ${datadir}/mime-info \
${datadir}/gnome-2.0"
inherit autotools pkgconfig gconf
EXTRA_AUTORECONF += "-I ${STAGING_DIR}/${HOST_SYS}/share/aclocal/gnome2-macros"
gnome_stage_includes() {
autotools_stage_includes
}

View File

@@ -0,0 +1,16 @@
DEPENDS_prepend = "coreutils-native virtual/libintl intltool-native "
GPE_TARBALL_SUFFIX ?= "gz"
SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.${GPE_TARBALL_SUFFIX}"
FILES_${PN} += "${datadir}/gpe ${datadir}/application-registry"
inherit gettext
gpe_do_compile() {
oe_runmake PREFIX=${prefix}
}
gpe_do_install() {
oe_runmake PREFIX=${prefix} DESTDIR=${D} install
}
EXPORT_FUNCTIONS do_compile do_install

View File

@@ -0,0 +1,156 @@
# IceCream distributed compiling support
#
# We need to create a tar.bz2 of our toolchain and set
# ICECC_VERSION, ICECC_CXX and ICEC_CC
#
def create_env(bb,d):
"""
Create a tar.bz of the current toolchain
"""
# Constin native-native compilation no environment needed if
# host prefix is empty (let us duplicate the query for ease)
prefix = bb.data.expand('${HOST_PREFIX}', d)
if len(prefix) == 0:
return ""
import tarfile
import socket
import time
import os
ice_dir = bb.data.expand('${CROSS_DIR}', d)
prefix = bb.data.expand('${HOST_PREFIX}' , d)
distro = bb.data.expand('${DISTRO}', d)
target_sys = bb.data.expand('${TARGET_SYS}', d)
#float = bb.data.getVar('${TARGET_FPU}', d)
float = "anyfloat"
name = socket.gethostname()
try:
os.stat(ice_dir + '/' + target_sys + '/lib/ld-linux.so.2')
os.stat(ice_dir + '/' + target_sys + '/bin/g++')
except:
return ""
VERSION = '3.4.3'
cross_name = prefix + distro + target_sys + float +VERSION+ name
tar_file = ice_dir + '/ice/' + cross_name + '.tar.bz2'
try:
os.stat(tar_file)
return tar_file
except:
try:
os.makedirs(ice_dir+'/ice')
except:
pass
# FIXME find out the version of the compiler
tar = tarfile.open(tar_file, 'w:bz2')
tar.add(ice_dir + '/' + target_sys + '/lib/ld-linux.so.2',
target_sys + 'cross/lib/ld-linux.so.2')
tar.add(ice_dir + '/' + target_sys + '/lib/ld-linux.so.2',
target_sys + 'cross/lib/ld-2.3.3.so')
tar.add(ice_dir + '/' + target_sys + '/lib/libc-2.3.3.so',
target_sys + 'cross/lib/libc-2.3.3.so')
tar.add(ice_dir + '/' + target_sys + '/lib/libc.so.6',
target_sys + 'cross/lib/libc.so.6')
tar.add(ice_dir + '/' + target_sys + '/bin/gcc',
target_sys + 'cross/usr/bin/gcc')
tar.add(ice_dir + '/' + target_sys + '/bin/g++',
target_sys + 'cross/usr/bin/g++')
tar.add(ice_dir + '/' + target_sys + '/bin/as',
target_sys + 'cross/usr/bin/as')
tar.add(ice_dir + '/lib/gcc/' + target_sys +'/'+ VERSION + '/specs',
target_sys+'cross/usr/lib/gcc/'+target_sys+'/'+VERSION+'/lib/specs')
tar.add(ice_dir + '/libexec/gcc/'+target_sys+'/' + VERSION + '/cc1',
target_sys + 'cross/usr/lib/gcc/'+target_sys+'/'+VERSION+'/lib/cc1')
tar.add(ice_dir + '/libexec/gcc/arm-linux/' + VERSION + '/cc1plus',
target_sys+'cross/usr/lib/gcc/'+target_sys+'/'+VERSION+'/lib/cc1plus')
tar.close()
return tar_file
def create_path(compilers, type, bb, d):
"""
Create Symlinks for the icecc in the staging directory
"""
import os
staging = bb.data.expand('${STAGING_DIR}', d) + "/ice/" + type
icecc = bb.data.getVar('ICECC_PATH', d)
# Create the dir if necessary
try:
os.stat(staging)
except:
os.makedirs(staging)
for compiler in compilers:
gcc_path = staging + "/" + compiler
try:
os.stat(gcc_path)
except:
os.symlink(icecc, gcc_path)
return staging + ":"
def use_icc_version(bb,d):
# Constin native native
prefix = bb.data.expand('${HOST_PREFIX}', d)
if len(prefix) == 0:
return "no"
native = bb.data.expand('${PN}', d)
blacklist = [ "-cross", "-native" ]
for black in blacklist:
if black in native:
return "no"
return "yes"
def icc_path(bb,d,compile):
native = bb.data.expand('${PN}', d)
blacklist = [ "ulibc", "glibc", "ncurses" ]
for black in blacklist:
if black in native:
return ""
if "-native" in native:
compile = False
if "-cross" in native:
compile = False
prefix = bb.data.expand('${HOST_PREFIX}', d)
if compile and len(prefix) != 0:
return create_path( [prefix+"gcc", prefix+"g++"], "cross", bb, d )
elif not compile or len(prefix) == 0:
return create_path( ["gcc", "g++"], "native", bb, d)
def icc_version(bb,d):
return create_env(bb,d)
#
# set the IceCream environment variables
do_configure_prepend() {
export PATH=${@icc_path(bb,d,False)}$PATH
export ICECC_CC="gcc"
export ICECC_CXX="g++"
}
do_compile_prepend() {
export PATH=${@icc_path(bb,d,True)}$PATH
export ICECC_CC="${HOST_PREFIX}gcc"
export ICECC_CXX="${HOST_PREFIX}g++"
if [ "${@use_icc_version(bb,d)}" = "yes" ]; then
export ICECC_VERSION="${@icc_version(bb,d)}"
fi
}

View File

@@ -0,0 +1,72 @@
inherit rootfs_ipk
# Images are generally built explicitly, do not need to be part of world.
EXCLUDE_FROM_WORLD = "1"
USE_DEVFS ?= "0"
DEPENDS += "makedevs-native"
def get_image_deps(d):
import bb
str = ""
for type in (bb.data.getVar('IMAGE_FSTYPES', d, 1) or "").split():
deps = bb.data.getVar('IMAGE_DEPENDS_%s' % type, d) or ""
if deps:
str += " %s" % deps
return str
DEPENDS += "${@get_image_deps(d)}"
IMAGE_DEVICE_TABLE ?= "${@bb.which(bb.data.getVar('BBPATH', d, 1), 'files/device_table-minimal.txt')}"
IMAGE_POSTPROCESS_COMMAND ?= ""
# Must call real_do_rootfs() from inside here, rather than as a separate
# task, so that we have a single fakeroot context for the whole process.
fakeroot do_rootfs () {
set -x
rm -rf ${IMAGE_ROOTFS}
if [ "${USE_DEVFS}" != "1" ]; then
mkdir -p ${IMAGE_ROOTFS}/dev
makedevs -r ${IMAGE_ROOTFS} -D ${IMAGE_DEVICE_TABLE}
fi
real_do_rootfs
insert_feed_uris
rm -f ${IMAGE_ROOTFS}${libdir}/ipkg/lists/oe
${IMAGE_PREPROCESS_COMMAND}
export TOPDIR=${TOPDIR}
for type in ${IMAGE_FSTYPES}; do
if test -z "$FAKEROOTKEY"; then
fakeroot -i ${TMPDIR}/fakedb.image bbimage -t $type -e ${FILE}
else
bbimage -n "${IMAGE_NAME}" -t "$type" -e "${FILE}"
fi
done
${IMAGE_POSTPROCESS_COMMAND}
}
insert_feed_uris () {
echo "Building feeds for [${DISTRO}].."
for line in ${FEED_URIS}
do
# strip leading and trailing spaces/tabs, then split into name and uri
line_clean="`echo "$line"|sed 's/^[ \t]*//;s/[ \t]*$//'`"
feed_name="`echo "$line_clean" | sed -n 's/\(.*\)##\(.*\)/\1/p'`"
feed_uri="`echo "$line_clean" | sed -n 's/\(.*\)##\(.*\)/\2/p'`"
echo "Added $feed_name feed with URL $feed_uri"
# insert new feed-sources
echo "src/gz $feed_name $feed_uri" >> ${IMAGE_ROOTFS}/etc/ipkg/${feed_name}-feed.conf
done
}

View File

@@ -0,0 +1,26 @@
#
# set the ARCH environment variable for kernel compilation (including
# modules). return value must match one of the architecture directories
# in the kernel source "arch" directory
#
valid_archs = "alpha cris ia64 m68knommu ppc sh \
sparc64 x86_64 arm h8300 m32r mips \
ppc64 sh64 um arm26 i386 m68k \
parisc s390 sparc v850"
def map_kernel_arch(a, d):
import bb, re
valid_archs = bb.data.getVar('valid_archs', d, 1).split()
if re.match('(i.86|athlon)$', a): return 'i386'
elif re.match('arm26$', a): return 'arm26'
elif re.match('armeb$', a): return 'arm'
elif re.match('powerpc$', a): return 'ppc'
elif re.match('mipsel$', a): return 'mips'
elif a in valid_archs: return a
else:
bb.error("cannot map '%s' to a linux kernel architecture" % a)
export ARCH = "${@map_kernel_arch(bb.data.getVar('TARGET_ARCH', d, 1), d)}"

View File

@@ -0,0 +1,391 @@
inherit module_strip
PROVIDES += "virtual/kernel"
DEPENDS += "virtual/${TARGET_PREFIX}depmod-${@get_kernelmajorversion('${PV}')} virtual/${TARGET_PREFIX}gcc${KERNEL_CCSUFFIX} update-modules"
inherit kernel-arch
export OS = "${TARGET_OS}"
export CROSS_COMPILE = "${TARGET_PREFIX}"
KERNEL_IMAGETYPE = "zImage"
KERNEL_PRIORITY = "${@bb.data.getVar('PV',d,1).split('-')[0].split('.')[-1]}"
# [jbowler 20051109] ${PV}${KERNEL_LOCALVERSION} is used throughout this
# .bbclass to (apparently) find the full 'uname -r' kernel version, this
# should be the same as UTS_RELEASE or (in this file) KERNEL_VERSION:
# KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
# but since this is not certain this overridable setting is used here:
KERNEL_RELEASE ?= "${PV}${KERNEL_LOCALVERSION}"
KERNEL_CCSUFFIX ?= ""
KERNEL_LDSUFFIX ?= ""
KERNEL_CC = "${CCACHE}${HOST_PREFIX}gcc${KERNEL_CCSUFFIX}"
KERNEL_LD = "${LD}${KERNEL_LDSUFFIX}"
KERNEL_OUTPUT = "arch/${ARCH}/boot/${KERNEL_IMAGETYPE}"
KERNEL_IMAGEDEST = "boot"
#
# configuration
#
export CMDLINE_CONSOLE = "console=${@bb.data.getVar("KERNEL_CONSOLE",d,1) or "ttyS0"}"
# parse kernel ABI version out of <linux/version.h>
def get_kernelversion(p):
import re
try:
f = open(p, 'r')
except IOError:
return None
l = f.readlines()
f.close()
r = re.compile("#define UTS_RELEASE \"(.*)\"")
for s in l:
m = r.match(s)
if m:
return m.group(1)
return None
def get_kernelmajorversion(p):
import re
r = re.compile("([0-9]+\.[0-9]+).*")
m = r.match(p);
if m:
return m.group(1)
return None
KERNEL_VERSION = "${@get_kernelversion('${S}/include/linux/version.h')}"
KERNEL_MAJOR_VERSION = "${@get_kernelmajorversion('${KERNEL_VERSION}')}"
KERNEL_LOCALVERSION ?= ""
# kernels are generally machine specific
PACKAGE_ARCH = "${MACHINE_ARCH}"
kernel_do_compile() {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake include/linux/version.h CC="${KERNEL_CC}" LD="${KERNEL_LD}"
if [ "${KERNEL_MAJOR_VERSION}" != "2.6" ]; then
oe_runmake dep CC="${KERNEL_CC}" LD="${KERNEL_LD}"
fi
oe_runmake ${KERNEL_IMAGETYPE} CC="${KERNEL_CC}" LD="${KERNEL_LD}"
if (grep -q -i -e '^CONFIG_MODULES=y$' .config); then
oe_runmake modules CC="${KERNEL_CC}" LD="${KERNEL_LD}"
else
oenote "no modules to compile"
fi
}
kernel_do_stage() {
ASMDIR=`readlink include/asm`
mkdir -p ${STAGING_KERNEL_DIR}/include/$ASMDIR
cp -fR include/$ASMDIR/* ${STAGING_KERNEL_DIR}/include/$ASMDIR/
ln -sf $ASMDIR ${STAGING_KERNEL_DIR}/include/asm
mkdir -p ${STAGING_KERNEL_DIR}/include/asm-generic
cp -fR include/asm-generic/* ${STAGING_KERNEL_DIR}/include/asm-generic/
mkdir -p ${STAGING_KERNEL_DIR}/include/linux
cp -fR include/linux/* ${STAGING_KERNEL_DIR}/include/linux/
mkdir -p ${STAGING_KERNEL_DIR}/include/net
cp -fR include/net/* ${STAGING_KERNEL_DIR}/include/net/
mkdir -p ${STAGING_KERNEL_DIR}/include/pcmcia
cp -fR include/pcmcia/* ${STAGING_KERNEL_DIR}/include/pcmcia/
if [ -d drivers/sound ]; then
# 2.4 alsa needs some headers from this directory
mkdir -p ${STAGING_KERNEL_DIR}/include/drivers/sound
cp -fR drivers/sound/*.h ${STAGING_KERNEL_DIR}/include/drivers/sound/
fi
install -m 0644 .config ${STAGING_KERNEL_DIR}/config-${KERNEL_RELEASE}
ln -sf config-${KERNEL_RELEASE} ${STAGING_KERNEL_DIR}/.config
ln -sf config-${KERNEL_RELEASE} ${STAGING_KERNEL_DIR}/kernel-config
echo "${KERNEL_VERSION}" >${STAGING_KERNEL_DIR}/kernel-abiversion
echo "${S}" >${STAGING_KERNEL_DIR}/kernel-source
echo "${KERNEL_CCSUFFIX}" >${STAGING_KERNEL_DIR}/kernel-ccsuffix
echo "${KERNEL_LDSUFFIX}" >${STAGING_KERNEL_DIR}/kernel-ldsuffix
[ -e Rules.make ] && install -m 0644 Rules.make ${STAGING_KERNEL_DIR}/
[ -e Makefile ] && install -m 0644 Makefile ${STAGING_KERNEL_DIR}/
# Check if arch/${ARCH}/Makefile exists and install it
if [ -e arch/${ARCH}/Makefile ]; then
install -d ${STAGING_KERNEL_DIR}/arch/${ARCH}
install -m 0644 arch/${ARCH}/Makefile ${STAGING_KERNEL_DIR}/arch/${ARCH}
fi
cp -fR include/config* ${STAGING_KERNEL_DIR}/include/
install -m 0644 ${KERNEL_OUTPUT} ${STAGING_KERNEL_DIR}/${KERNEL_IMAGETYPE}
install -m 0644 System.map ${STAGING_KERNEL_DIR}/System.map-${KERNEL_RELEASE}
[ -e Module.symvers ] && install -m 0644 Module.symvers ${STAGING_KERNEL_DIR}/
cp -fR scripts ${STAGING_KERNEL_DIR}/
}
kernel_do_install() {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
if (grep -q -i -e '^CONFIG_MODULES=y$' .config); then
oe_runmake DEPMOD=echo INSTALL_MOD_PATH="${D}" modules_install
else
oenote "no modules to install"
fi
install -d ${D}/${KERNEL_IMAGEDEST}
install -d ${D}/boot
install -m 0644 ${KERNEL_OUTPUT} ${D}/${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-${KERNEL_RELEASE}
install -m 0644 System.map ${D}/boot/System.map-${KERNEL_RELEASE}
install -m 0644 .config ${D}/boot/config-${KERNEL_RELEASE}
install -d ${D}/etc/modutils
# Check if scripts/genksyms exists and if so, build it
if [ -e scripts/genksyms/ ]; then
oe_runmake SUBDIRS="scripts/genksyms"
fi
cp -fR scripts ${STAGING_KERNEL_DIR}/
}
kernel_do_configure() {
yes '' | oe_runmake oldconfig
}
pkg_postinst_kernel () {
update-alternatives --install /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE} ${KERNEL_IMAGETYPE} /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-${KERNEL_RELEASE} ${KERNEL_PRIORITY} || true
}
pkg_postrm_kernel () {
update-alternatives --remove ${KERNEL_IMAGETYPE} /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-${KERNEL_RELEASE} || true
}
inherit cml1
EXPORT_FUNCTIONS do_compile do_install do_stage do_configure
PACKAGES = "kernel kernel-image kernel-dev"
FILES = ""
FILES_kernel-image = "/boot/${KERNEL_IMAGETYPE}*"
FILES_kernel-dev = "/boot/System.map* /boot/config*"
RDEPENDS_kernel = "kernel-image-${KERNEL_VERSION}"
PKG_kernel-image = "kernel-image-${KERNEL_VERSION}"
ALLOW_EMPTY_kernel = "1"
ALLOW_EMPTY_kernel-image = "1"
pkg_postinst_modules () {
if [ -n "$D" ]; then
${HOST_PREFIX}depmod -A -b $D -F ${STAGING_KERNEL_DIR}/System.map-${KERNEL_RELEASE} ${KERNEL_VERSION}
else
depmod -A
update-modules || true
fi
}
pkg_postrm_modules () {
update-modules || true
}
autoload_postinst_fragment() {
if [ x"$D" = "x" ]; then
modprobe %s || true
fi
}
# autoload defaults (alphabetically sorted)
module_autoload_hidp = "hidp"
module_autoload_ipv6 = "ipv6"
module_autoload_ipsec = "ipsec"
module_autoload_ircomm-tty = "ircomm-tty"
module_autoload_rfcomm = "rfcomm"
module_autoload_sa1100-rtc = "sa1100-rtc"
# alias defaults (alphabetically sorted)
module_conf_af_packet = "alias net-pf-17 af_packet"
module_conf_bluez = "alias net-pf-31 bluez"
module_conf_bnep = "alias bt-proto-4 bnep"
module_conf_hci_uart = "alias tty-ldisc-15 hci_uart"
module_conf_l2cap = "alias bt-proto-0 l2cap"
module_conf_sco = "alias bt-proto-2 sco"
module_conf_rfcomm = "alias bt-proto-3 rfcomm"
python populate_packages_prepend () {
def extract_modinfo(file):
import os, re
tmpfile = os.tmpnam()
cmd = "PATH=\"%s\" %sobjcopy -j .modinfo -O binary %s %s" % (bb.data.getVar("PATH", d, 1), bb.data.getVar("HOST_PREFIX", d, 1) or "", file, tmpfile)
os.system(cmd)
f = open(tmpfile)
l = f.read().split("\000")
f.close()
os.unlink(tmpfile)
exp = re.compile("([^=]+)=(.*)")
vals = {}
for i in l:
m = exp.match(i)
if not m:
continue
vals[m.group(1)] = m.group(2)
return vals
def parse_depmod():
import os, re
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined")
return
kernelver = bb.data.getVar('KERNEL_RELEASE', d, 1)
kernelver_stripped = kernelver
m = re.match('^(.*-hh.*)[\.\+].*$', kernelver)
if m:
kernelver_stripped = m.group(1)
path = bb.data.getVar("PATH", d, 1)
host_prefix = bb.data.getVar("HOST_PREFIX", d, 1) or ""
cmd = "PATH=\"%s\" %sdepmod -n -a -r -b %s -F %s/boot/System.map-%s %s" % (path, host_prefix, dvar, dvar, kernelver, kernelver_stripped)
f = os.popen(cmd, 'r')
deps = {}
pattern0 = "^(.*\.k?o):..*$"
pattern1 = "^(.*\.k?o):\s*(.*\.k?o)\s*$"
pattern2 = "^(.*\.k?o):\s*(.*\.k?o)\s*\\\$"
pattern3 = "^\t(.*\.k?o)\s*\\\$"
pattern4 = "^\t(.*\.k?o)\s*$"
line = f.readline()
while line:
if not re.match(pattern0, line):
line = f.readline()
continue
m1 = re.match(pattern1, line)
if m1:
deps[m1.group(1)] = m1.group(2).split()
else:
m2 = re.match(pattern2, line)
if m2:
deps[m2.group(1)] = m2.group(2).split()
line = f.readline()
m3 = re.match(pattern3, line)
while m3:
deps[m2.group(1)].extend(m3.group(1).split())
line = f.readline()
m3 = re.match(pattern3, line)
m4 = re.match(pattern4, line)
deps[m2.group(1)].extend(m4.group(1).split())
line = f.readline()
f.close()
return deps
def get_dependencies(file, pattern, format):
file = file.replace(bb.data.getVar('D', d, 1) or '', '', 1)
if module_deps.has_key(file):
import os.path, re
dependencies = []
for i in module_deps[file]:
m = re.match(pattern, os.path.basename(i))
if not m:
continue
on = legitimize_package_name(m.group(1))
dependency_pkg = format % on
v = bb.data.getVar("PARALLEL_INSTALL_MODULES", d, 1) or "0"
if v == "1":
kv = bb.data.getVar("KERNEL_MAJOR_VERSION", d, 1)
dependency_pkg = "%s-%s" % (dependency_pkg, kv)
dependencies.append(dependency_pkg)
return dependencies
return []
def frob_metadata(file, pkg, pattern, format, basename):
import re
vals = extract_modinfo(file)
dvar = bb.data.getVar('D', d, 1)
# If autoloading is requested, output /etc/modutils/<name> and append
# appropriate modprobe commands to the postinst
autoload = bb.data.getVar('module_autoload_%s' % basename, d, 1)
if autoload:
name = '%s/etc/modutils/%s' % (dvar, basename)
f = open(name, 'w')
for m in autoload.split():
f.write('%s\n' % m)
f.close()
postinst = bb.data.getVar('pkg_postinst_%s' % pkg, d, 1)
if not postinst:
bb.fatal("pkg_postinst_%s not defined" % pkg)
postinst += bb.data.getVar('autoload_postinst_fragment', d, 1) % autoload
bb.data.setVar('pkg_postinst_%s' % pkg, postinst, d)
# Write out any modconf fragment
modconf = bb.data.getVar('module_conf_%s' % basename, d, 1)
if modconf:
name = '%s/etc/modutils/%s.conf' % (dvar, basename)
f = open(name, 'w')
f.write("%s\n" % modconf)
f.close()
files = bb.data.getVar('FILES_%s' % pkg, d, 1)
files = "%s /etc/modutils/%s /etc/modutils/%s.conf" % (files, basename, basename)
bb.data.setVar('FILES_%s' % pkg, files, d)
if vals.has_key("description"):
old_desc = bb.data.getVar('DESCRIPTION_' + pkg, d, 1) or ""
bb.data.setVar('DESCRIPTION_' + pkg, old_desc + "; " + vals["description"], d)
rdepends_str = bb.data.getVar('RDEPENDS_' + pkg, d, 1)
if rdepends_str:
rdepends = rdepends_str.split()
else:
rdepends = []
rdepends.extend(get_dependencies(file, pattern, format))
bb.data.setVar('RDEPENDS_' + pkg, ' '.join(rdepends), d)
module_deps = parse_depmod()
module_regex = '^(.*)\.k?o$'
module_pattern = 'kernel-module-%s'
postinst = bb.data.getVar('pkg_postinst_modules', d, 1)
postrm = bb.data.getVar('pkg_postrm_modules', d, 1)
do_split_packages(d, root='/lib/modules', file_regex=module_regex, output_pattern=module_pattern, description='%s kernel module', postinst=postinst, postrm=postrm, recursive=True, hook=frob_metadata, extra_depends='update-modules kernel-image-%s' % bb.data.getVar("KERNEL_VERSION", d, 1))
import re, os
metapkg = "kernel-modules"
bb.data.setVar('ALLOW_EMPTY_' + metapkg, "1", d)
bb.data.setVar('FILES_' + metapkg, "", d)
blacklist = [ 'kernel-dev', 'kernel-image' ]
for l in module_deps.values():
for i in l:
pkg = module_pattern % legitimize_package_name(re.match(module_regex, os.path.basename(i)).group(1))
blacklist.append(pkg)
metapkg_rdepends = []
packages = bb.data.getVar('PACKAGES', d, 1).split()
for pkg in packages[1:]:
if not pkg in blacklist and not pkg in metapkg_rdepends:
metapkg_rdepends.append(pkg)
bb.data.setVar('RDEPENDS_' + metapkg, ' '.join(metapkg_rdepends), d)
bb.data.setVar('DESCRIPTION_' + metapkg, 'Kernel modules meta package', d)
packages.append(metapkg)
bb.data.setVar('PACKAGES', ' '.join(packages), d)
v = bb.data.getVar("PARALLEL_INSTALL_MODULES", d, 1) or "0"
if v == "1":
kv = bb.data.getVar("KERNEL_MAJOR_VERSION", d, 1)
packages = bb.data.getVar("PACKAGES", d, 1)
module_re = re.compile("^kernel-module-")
for p in packages.split():
if not module_re.match(p):
continue
pkg = bb.data.getVar("PKG_%s" % p, d, 1) or p
newpkg = "%s-%s" % (pkg, kv)
bb.data.setVar("PKG_%s" % p, newpkg, d)
rprovides = bb.data.getVar("RPROVIDES_%s" % p, d, 1)
if rprovides:
rprovides = "%s %s" % (rprovides, pkg)
else:
rprovides = pkg
bb.data.setVar("RPROVIDES_%s" % p, rprovides, d)
}

View File

@@ -0,0 +1,9 @@
PACKAGES = "${PN} ${PN}-dev ${PN}-doc ${PN}-bin"
FILES_${PN} = "${libexecdir} ${libdir}/lib*.so.* \
${sysconfdir} ${sharedstatedir} ${localstatedir} \
/lib/*.so* ${datadir}/${PN} ${libdir}/${PN}"
FILES_${PN}-dev = "${includedir} ${libdir}/lib*.so ${libdir}/*.la \
${libdir}/*.a ${libdir}/pkgconfig /lib/*.a /lib/*.o \
${datadir}/aclocal ${bindir}/*-config"
FILES_${PN}-bin = "${bindir} ${sbindir} /bin /sbin"

View File

@@ -0,0 +1,19 @@
def get_kernelmajorversion(p):
import re
r = re.compile("([0-9]+\.[0-9]+).*")
m = r.match(p);
if m:
return m.group(1)
return None
def linux_module_packages(s, d):
import bb, os.path
suffix = ""
if (bb.data.getVar("PARALLEL_INSTALL_MODULES", d, 1) == "1"):
file = bb.data.expand('${STAGING_KERNEL_DIR}/kernel-abiversion', d)
if (os.path.exists(file)):
suffix = "-%s" % (get_kernelmajorversion(base_read_file(file)))
return " ".join(map(lambda s: "kernel-module-%s%s" % (s.lower().replace('_', '-').replace('@', '+'), suffix), s.split()))
# that's all

View File

@@ -0,0 +1,17 @@
inherit module_strip
inherit kernel-arch
export OS = "${TARGET_OS}"
export CROSS_COMPILE = "${TARGET_PREFIX}"
export KERNEL_VERSION = "${@base_read_file('${STAGING_KERNEL_DIR}/kernel-abiversion')}"
export KERNEL_SOURCE = "${@base_read_file('${STAGING_KERNEL_DIR}/kernel-source')}"
KERNEL_OBJECT_SUFFIX = "${@[".o", ".ko"][base_read_file('${STAGING_KERNEL_DIR}/kernel-abiversion') > "2.6.0"]}"
KERNEL_CCSUFFIX = "${@base_read_file('${STAGING_KERNEL_DIR}/kernel-ccsuffix')}"
KERNEL_LDSUFFIX = "${@base_read_file('${STAGING_KERNEL_DIR}/kernel-ldsuffix')}"
KERNEL_CC = "${CCACHE}${HOST_PREFIX}gcc${KERNEL_CCSUFFIX}"
KERNEL_LD = "${LD}${KERNEL_LDSUFFIX}"
# kernel modules are generally machine specific
PACKAGE_ARCH = "${MACHINE_ARCH}"

View File

@@ -0,0 +1,51 @@
RDEPENDS += "kernel (${KERNEL_VERSION})"
DEPENDS += "virtual/kernel"
inherit module-base
python populate_packages_prepend() {
v = bb.data.getVar("PARALLEL_INSTALL_MODULES", d, 1) or "0"
if v == "1":
kv = bb.data.getVar("KERNEL_VERSION", d, 1)
packages = bb.data.getVar("PACKAGES", d, 1)
for p in packages.split():
pkg = bb.data.getVar("PKG_%s" % p, d, 1) or p
newpkg = "%s-%s" % (pkg, kv)
bb.data.setVar("PKG_%s" % p, newpkg, d)
rprovides = bb.data.getVar("RPROVIDES_%s" % p, d, 1)
if rprovides:
rprovides = "%s %s" % (rprovides, pkg)
else:
rprovides = pkg
bb.data.setVar("RPROVIDES_%s" % p, rprovides, d)
}
module_do_compile() {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake KERNEL_PATH=${STAGING_KERNEL_DIR} \
KERNEL_SRC=${STAGING_KERNEL_DIR} \
KERNEL_VERSION=${KERNEL_VERSION} \
CC="${KERNEL_CC}" LD="${KERNEL_LD}" \
${MAKE_TARGETS}
}
module_do_install() {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
oe_runmake DEPMOD=echo INSTALL_MOD_PATH="${D}" CC="${KERNEL_CC}" LD="${KERNEL_LD}" modules_install
}
pkg_postinst_append () {
if [ -n "$D" ]; then
exit 1
fi
depmod -A
update-modules || true
}
pkg_postrm_append () {
update-modules || true
}
EXPORT_FUNCTIONS do_compile do_install
FILES_${PN} = "/etc /lib/modules"

View File

@@ -0,0 +1,18 @@
#DEPENDS_append = " module-strip"
do_strip_modules () {
for p in ${PACKAGES}; do
if test -e ${WORKDIR}/install/$p/lib/modules; then
modules="`find ${WORKDIR}/install/$p/lib/modules -name \*${KERNEL_OBJECT_SUFFIX}`"
if [ -n "$modules" ]; then
${STRIP} -v -g $modules
# NM="${CROSS_DIR}/bin/${HOST_PREFIX}nm" OBJCOPY="${CROSS_DIR}/bin/${HOST_PREFIX}objcopy" strip_module $modules
fi
fi
done
}
python do_package_append () {
if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, 1) != '1'):
bb.build.exec_func('do_strip_modules', d)
}

View File

@@ -0,0 +1,53 @@
SECTION = "x11/utils"
DEPENDS += "gnu-config-native virtual/libintl xt libxi \
zip-native gtk+ orbit2 libidl-native"
LICENSE = "MPL NPL"
SRC_URI += "file://mozconfig"
inherit gettext
EXTRA_OECONF = "--target=${TARGET_SYS} --host=${BUILD_SYS} \
--build=${BUILD_SYS} --prefix=${prefix}"
EXTRA_OEMAKE = "'HOST_LIBIDL_LIBS=${HOST_LIBIDL_LIBS}' \
'HOST_LIBIDL_CFLAGS=${HOST_LIBIDL_CFLAGS}'"
SELECTED_OPTIMIZATION = "-Os -fsigned-char -fno-strict-aliasing"
export CROSS_COMPILE = "1"
export MOZCONFIG = "${WORKDIR}/mozconfig"
export MOZ_OBJDIR = "${S}"
export CONFIGURE_ARGS = "${EXTRA_OECONF}"
export HOST_LIBIDL_CFLAGS = "`${HOST_LIBIDL_CONFIG} --cflags`"
export HOST_LIBIDL_LIBS = "`${HOST_LIBIDL_CONFIG} --libs`"
export HOST_LIBIDL_CONFIG = "PKG_CONFIG_PATH=${STAGING_BINDIR}/../share/pkgconfig pkg-config libIDL-2.0"
export HOST_CC = "${BUILD_CC}"
export HOST_CXX = "${BUILD_CXX}"
export HOST_CFLAGS = "${BUILD_CFLAGS}"
export HOST_CXXFLAGS = "${BUILD_CXXFLAGS}"
export HOST_LDFLAGS = "${BUILD_LDFLAGS}"
export HOST_RANLIB = "${BUILD_RANLIB}"
export HOST_AR = "${BUILD_AR}"
mozilla_do_configure() {
(
set -e
for cg in `find ${S} -name config.guess`; do
install -m 0755 \
${STAGING_BINDIR}/../share/gnu-config/config.guess \
${STAGING_BINDIR}/../share/gnu-config/config.sub \
`dirname $cg`/
done
)
oe_runmake -f client.mk ${MOZ_OBJDIR}/Makefile \
${MOZ_OBJDIR}/config.status
}
mozilla_do_compile() {
oe_runmake -f client.mk build_all
}
mozilla_do_install() {
oe_runmake DESTDIR="${D}" destdir="${D}" install
}
EXPORT_FUNCTIONS do_configure do_compile do_install

View File

@@ -0,0 +1,3 @@
STAMP = "${TMPDIR}/stamps/${PACKAGE_ARCH}-${HOST_OS}/${PF}"
WORKDIR = "${TMPDIR}/work/${PACKAGE_ARCH}-${HOST_OS}/${PF}"
STAGING_KERNEL_DIR = "${STAGING_DIR}/${PACKAGE_ARCH}-${HOST_OS}/kernel"

View File

@@ -0,0 +1,69 @@
inherit base
# Native packages are built indirectly via dependency,
# no need for them to be a direct target of 'world'
EXCLUDE_FROM_WORLD = "1"
PACKAGES = ""
PACKAGE_ARCH = "native"
TARGET_ARCH = "${BUILD_ARCH}"
TARGET_OS = "${BUILD_OS}"
TARGET_VENDOR = "${BUILD_VENDOR}"
TARGET_PREFIX = "${BUILD_PREFIX}"
TARGET_CC_ARCH = "${BUILD_CC_ARCH}"
HOST_ARCH = "${BUILD_ARCH}"
HOST_OS = "${BUILD_OS}"
HOST_VENDOR = "${BUILD_VENDOR}"
HOST_PREFIX = "${BUILD_PREFIX}"
HOST_CC_ARCH = "${BUILD_CC_ARCH}"
CPPFLAGS = "${BUILD_CPPFLAGS}"
CFLAGS = "${BUILD_CFLAGS}"
CXXFLAGS = "${BUILD_CFLAGS}"
LDFLAGS = "${BUILD_LDFLAGS}"
# Path prefixes
base_prefix = "${exec_prefix}"
prefix = "${STAGING_DIR}"
exec_prefix = "${STAGING_DIR}/${BUILD_ARCH}-${BUILD_OS}"
# Base paths
base_bindir = "${base_prefix}/bin"
base_sbindir = "${base_prefix}/bin"
base_libdir = "${base_prefix}/lib"
# Architecture independent paths
sysconfdir = "${prefix}/etc"
sharedstatedir = "${prefix}/com"
localstatedir = "${prefix}/var"
infodir = "${datadir}/info"
mandir = "${datadir}/man"
docdir = "${datadir}/doc"
servicedir = "${prefix}/srv"
# Architecture dependent paths
bindir = "${exec_prefix}/bin"
sbindir = "${exec_prefix}/bin"
libexecdir = "${exec_prefix}/libexec"
libdir = "${exec_prefix}/lib"
includedir = "${exec_prefix}/include"
oldincludedir = "${exec_prefix}/include"
# Datadir is made arch dependent here, primarily
# for autoconf macros, and other things that
# may be manipulated to handle crosscompilation
# issues.
datadir = "${exec_prefix}/share"
do_stage () {
if [ "${INHIBIT_NATIVE_STAGE_INSTALL}" != "1" ]
then
oe_runmake install
fi
}
do_install () {
true
}

View File

@@ -0,0 +1,18 @@
NSLU2_SLUGIMAGE_ARGS ?= ""
nslu2_pack_image () {
install -d ${DEPLOY_DIR_IMAGE}/slug
install -m 0644 ${STAGING_LIBDIR}/nslu2-binaries/RedBoot \
${STAGING_LIBDIR}/nslu2-binaries/Trailer \
${STAGING_LIBDIR}/nslu2-binaries/SysConf \
${DEPLOY_DIR_IMAGE}/slug/
install -m 0644 ${DEPLOY_DIR_IMAGE}/zImage-${IMAGE_BASENAME} ${DEPLOY_DIR_IMAGE}/slug/vmlinuz
install -m 0644 ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.jffs2 ${DEPLOY_DIR_IMAGE}/slug/flashdisk.jffs2
cd ${DEPLOY_DIR_IMAGE}/slug
slugimage -p -b RedBoot -s SysConf -r Ramdisk:1,Flashdisk:flashdisk.jffs2 -t Trailer \
-o ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.flashdisk.img ${NSLU2_SLUGIMAGE_ARGS}
rm -rf ${DEPLOY_DIR_IMAGE}/slug
}
EXTRA_IMAGEDEPENDS += 'slugimage-native nslu2-linksys-firmware'
IMAGE_POSTPROCESS_COMMAND += "nslu2_pack_image; "

View File

@@ -0,0 +1,4 @@
MIRRORS_append () {
ftp://.*/.*/ http://sources.nslu2-linux.org/sources/
http://.*/.*/ http://sources.nslu2-linux.org/sources/
}

View File

@@ -0,0 +1,18 @@
NSLU2_SLUGIMAGE_ARGS ?= ""
nslu2_pack_image () {
install -d ${DEPLOY_DIR_IMAGE}/slug
install -m 0644 ${STAGING_LIBDIR}/nslu2-binaries/RedBoot \
${STAGING_LIBDIR}/nslu2-binaries/Trailer \
${STAGING_LIBDIR}/nslu2-binaries/SysConf \
${DEPLOY_DIR_IMAGE}/slug/
install -m 0644 ${DEPLOY_DIR_IMAGE}/zImage-${IMAGE_BASENAME} ${DEPLOY_DIR_IMAGE}/slug/vmlinuz
install -m 0644 ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.ext2.gz ${DEPLOY_DIR_IMAGE}/slug/ramdisk.ext2.gz
cd ${DEPLOY_DIR_IMAGE}/slug
slugimage -p -b RedBoot -s SysConf -r Ramdisk:ramdisk.ext2.gz -t Trailer \
-o ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.ramdisk.img ${NSLU2_SLUGIMAGE_ARGS}
rm -rf ${DEPLOY_DIR_IMAGE}/slug
}
EXTRA_IMAGEDEPENDS += 'slugimage-native nslu2-linksys-firmware'
IMAGE_POSTPROCESS_COMMAND += "nslu2_pack_image; "

View File

@@ -0,0 +1,6 @@
MIRRORS_append () {
ftp://.*/.*/ http://meshcube.org/nylon/stable/sources/
http://.*/.*/ http://meshcube.org/nylon/stable/sources/
ftp://.*/.*/ http://meshcube.org/nylon/unstable/sources/
http://.*/.*/ http://meshcube.org/nylon/unstable/sources/
}

View File

@@ -0,0 +1,16 @@
#
# Because base.oeclasses set the variable
#
# do_fetch[nostamp] = "1"
# do_build[nostamp] = "1"
#
# for every build we're doing oemake calls all of the phases to check if
# something new is to download. This class unset's this nostamp flag. This
# makes a package "finished", once it's completely build.
#
# This means that the subsequent builds are faster, but when you change the
# behaviour of the package, e.g. by adding INHERIT="package_ipk", you won't
# get the ipk file except you delete the build stamp manually or all of them
# with oebuild clean <oe-file>.
do_build[nostamp] = ""

View File

@@ -0,0 +1,174 @@
addtask lint before do_fetch
do_lint[nostamp] = 1
python do_lint() {
def testVar(var, explain=None):
try:
s = d[var]
return s["content"]
except KeyError:
bb.error("%s is not set" % var)
if explain: bb.note(explain)
return None
##############################
# Test that DESCRIPTION exists
#
testVar("DESCRIPTION")
##############################
# Test that HOMEPAGE exists
#
s = testVar("HOMEPAGE")
if s=="unknown":
bb.error("HOMEPAGE is not set")
elif not s.startswith("http://"):
bb.error("HOMEPAGE doesn't start with http://")
##############################
# Test for valid LICENSE
#
valid_licenses = {
"GPL-2" : "GPLv2",
"GPL LGPL FDL" : True,
"GPL PSF" : True,
"GPL/QPL" : True,
"GPL" : True,
"GPLv2" : True,
"IBM" : True,
"LGPL GPL" : True,
"LGPL" : True,
"MIT" : True,
"OSL" : True,
"Perl" : True,
"Public Domain" : True,
"QPL" : "GPL/QPL",
}
s = testVar("LICENSE")
if s=="unknown":
bb.error("LICENSE is not set")
elif s.startswith("Vendor"):
pass
else:
try:
newlic = valid_licenses[s]
if newlic == False:
bb.note("LICENSE '%s' is not recommended" % s)
elif newlic != True:
bb.note("LICENSE '%s' is not recommended, better use '%s'" % (s, newsect))
except:
bb.note("LICENSE '%s' is not recommended" % s)
##############################
# Test for valid MAINTAINER
#
s = testVar("MAINTAINER")
if s=="OpenEmbedded Team <oe@handhelds.org>":
bb.error("explicit MAINTAINER is missing, using default")
elif s and s.find("@") == -1:
bb.error("You forgot to put an e-mail address into MAINTAINER")
##############################
# Test for valid SECTION
#
# if Correct section: True section name is valid
# False section name is invalid, no suggestion
# string section name is invalid, better name suggested
#
valid_sections = {
# Current Section Correct section
"apps" : True,
"audio" : True,
"base" : True,
"console/games" : True,
"console/net" : "console/network",
"console/network" : True,
"console/utils" : True,
"devel" : True,
"developing" : "devel",
"devel/python" : True,
"fonts" : True,
"games" : True,
"games/libs" : True,
"gnome/base" : True,
"gnome/libs" : True,
"gpe" : True,
"gpe/libs" : True,
"gui" : False,
"libc" : "libs",
"libs" : True,
"libs/net" : True,
"multimedia" : True,
"net" : "network",
"NET" : "network",
"network" : True,
"opie/applets" : True,
"opie/applications" : True,
"opie/base" : True,
"opie/codecs" : True,
"opie/decorations" : True,
"opie/fontfactories" : True,
"opie/fonts" : True,
"opie/games" : True,
"opie/help" : True,
"opie/inputmethods" : True,
"opie/libs" : True,
"opie/multimedia" : True,
"opie/pim" : True,
"opie/setting" : "opie/settings",
"opie/settings" : True,
"opie/Shell" : False,
"opie/styles" : True,
"opie/today" : True,
"scientific" : True,
"utils" : True,
"x11" : True,
"x11/libs" : True,
"x11/wm" : True,
}
s = testVar("SECTION")
if s:
try:
newsect = valid_sections[s]
if newsect == False:
bb.note("SECTION '%s' is not recommended" % s)
elif newsect != True:
bb.note("SECTION '%s' is not recommended, better use '%s'" % (s, newsect))
except:
bb.note("SECTION '%s' is not recommended" % s)
if not s.islower():
bb.error("SECTION should only use lower case")
##############################
# Test for valid PRIORITY
#
valid_priorities = {
"standard" : True,
"required" : True,
"optional" : True,
"extra" : True,
}
s = testVar("PRIORITY")
if s:
try:
newprio = valid_priorities[s]
if newprio == False:
bb.note("PRIORITY '%s' is not recommended" % s)
elif newprio != True:
bb.note("PRIORITY '%s' is not recommended, better use '%s'" % (s, newprio))
except:
bb.note("PRIORITY '%s' is not recommended" % s)
if not s.islower():
bb.error("PRIORITY should only use lower case")
}

View File

@@ -0,0 +1,99 @@
#
# This oeclass takes care about some of the itchy details of installing parts
# of Opie applications. Depending on quicklaunch or not, plugin or not, the
# TARGET is either a shared object, a shared object with a link to quicklauncher,
# or a usual binary.
#
# You have to provide two things: 1.) A proper SECTION field, and 2.) a proper APPNAME
# Then opie.oeclass will:
# * create the directory for the binary and install the binary file(s)
# * for applications: create the directory for the .desktop and install the .desktop file
# * for quicklauncher applications: create the startup symlink to the quicklauncher
# You can override the automatic detection of APPTYPE, valid values are 'quicklaunch', 'binary', 'plugin'
# You can override the default location of APPDESKTOP (<workdir>/apps/<section>/)
#
inherit palmtop
DEPENDS_prepend = "${@["libopie2 ", ""][(bb.data.getVar('PN', d, 1) == 'libopie2')]}"
# to be consistent, put all targets into workdir
EXTRA_QMAKEVARS_POST_append = " DESTDIR=${S}"
# Opie standard TAG value
TAG = "${@'v' + bb.data.getVar('PV',d,1).replace('.', '_')}"
# plan for later:
# add common scopes for opie applications, see qmake-native/common.pro
# qmake should care about all the details then. qmake can do that, i know it :)
#
python opie_do_opie_install() {
import os, shutil
section = bb.data.getVar( "SECTION", d ).split( '/' )[1] or "Applications"
section = section.title()
if section in ( "Base", "Libs" ):
bb.note( "Section = Base or Libs. Target won't be installed automatically." )
return
# SECTION : BINDIR DESKTOPDIR
dirmap = { "Applets" : ( "/plugins/applets", None ),
"Applications" : ( "<BINDIR>", "/apps/Applications" ),
"Multimedia" : ( "<BINDIR>", "/apps/Applications" ),
"Games" : ( "<BINDIR>", "/apps/Games" ),
"Settings" : ( "<BINDIR>", "/apps/Settings" ),
"Pim" : ( "<BINDIR>", "/apps/1Pim" ),
"Examples" : ( "<BINDIR>", "/apps/Examples" ),
"Shell" : ( "/bin", "/apps/Opie-SH" ),
"Codecs" : ( "/plugins/codecs", None ),
"Decorations" : ( "/plugins/decorations", None ),
"Inputmethods" : ( "/plugins/inputmethods", None ),
"Fontfactories" : ( "/plugins/fontfactories", None ),
"Security" : ( "/plugins/security", None ),
"Styles" : ( "/plugins/styles", None ),
"Today" : ( "/plugins/today", None ),
"Datebook" : ( "/plugins/holidays", None ),
"Networksettings" : ( "/plugins/networksettings", None ) }
if section not in dirmap:
raise ValueError, "Unknown section '%s'. Valid sections are: %s" % ( section, dirmap.keys() )
bindir, desktopdir = dirmap[section]
APPNAME = bb.data.getVar( "APPNAME", d, True ) or bb.data.getVar( "PN", d, True )
APPTYPE = bb.data.getVar( "APPTYPE", d, True )
if not APPTYPE:
if bindir == "<BINDIR>":
APPTYPE = "quicklaunch"
else:
APPTYPE = "plugin"
appmap = { "binary":"/bin", "quicklaunch":"/plugins/application" }
if bindir == "<BINDIR>": bindir = appmap[APPTYPE]
bb.note( "Section='%s', bindir='%s', desktopdir='%s', name='%s', type='%s'" %
( section, bindir, desktopdir, APPNAME, APPTYPE ) )
S = bb.data.getVar( "S", d, 1 )
D = "%s/image" % bb.data.getVar( "WORKDIR", d, True )
WORKDIR = bb.data.getVar( "WORKDIR", d, True )
palmtopdir = bb.data.getVar( "palmtopdir", d )
APPDESKTOP = bb.data.getVar( "APPDESKTOP", d, True ) or "%s/%s" % ( WORKDIR, desktopdir )
if desktopdir is not None:
os.system( "install -d %s%s%s/" % ( D, palmtopdir, desktopdir ) )
os.system( "install -m 0644 %s/%s.desktop %s%s%s/" % ( APPDESKTOP, APPNAME, D, palmtopdir, desktopdir ) )
os.system( "install -d %s%s%s/" % ( D, palmtopdir, bindir ) )
if APPTYPE == "binary":
os.system( "install -m 0755 %s/%s %s%s%s/" % ( S, APPNAME, D, palmtopdir, bindir ) )
elif APPTYPE == "quicklaunch":
os.system( "install -m 0755 %s/lib%s.so %s%s%s/" % ( S, APPNAME, D, palmtopdir, bindir ) )
os.system( "install -d %s%s/bin/" % ( D, palmtopdir ) )
os.system( "ln -sf %s/bin/quicklauncher %s%s/bin/%s" % ( palmtopdir, D, palmtopdir, APPNAME ) )
elif APPTYPE == "plugin":
os.system( "install -m 0755 %s/lib%s.so %s%s%s/" % ( S, APPNAME, D, palmtopdir, bindir ) )
}
EXPORT_FUNCTIONS do_opie_install
addtask opie_install after do_compile before do_populate_staging

View File

@@ -0,0 +1,163 @@
# classes/opie_i18n.oeclass Matthias 'CoreDump' Hentges 16-10-2004
#
# Automatically builds i18n ipks for opie packages. It downloads opie-i18n from opie CVS
# and tries to guess the name of the .ts file based on the package name:
# ${PN}.ts, lib${PN}.ts and opie-${PN}.ts are all valid. The .ts "guessing" can be
# disabled by setting I18N_FILES in the .oe file.
#
# Todo:
#
I18N_STATS = "1"
SRC_URI += "${HANDHELDS_CVS};module=opie/i18n"
DEPENDS += "opie-i18n"
die () {
echo -e "opie_18n: ERROR: $1"
exit 1
}
python do_build_opie_i18n_data() {
import os, bb, re
workdir = bb.data.getVar("WORKDIR", d, 1)
packages = bb.data.getVar("PACKAGES", d, 1)
files = bb.data.getVar("FILES", d, 1)
section = bb.data.getVar("SECTION", d, 1)
pn = bb.data.getVar("PN", d, 1)
rdepends = bb.data.getVar("RDEPENDS", d, 1)
if os.path.exists(workdir + "/PACKAGES.tmp"):
fd = open(workdir + "/PACKAGES.tmp", 'r')
lines = fd.readlines()
fd.close()
bb.data.setVar('PACKAGES', " ".join(lines).lower() + " " + packages, d)
fd = open(workdir + "/FILES.tmp", 'r')
lines = fd.readlines()
fd.close()
for l in lines:
x = re.split("\#", l)
bb.data.setVar('FILES_%s' % x[0].lower(), " " + x[1].strip('\n'), d)
bb.data.setVar('SECTION_%s' % x[0].lower(), "opie/translations", d)
bb.data.setVar('RDEPENDS_%s' % x[0].lower(), pn, d)
bb.data.setVar('SECTION_%s' % pn, section, d)
bb.data.setVar('RDEPENDS', rdepends, d)
else:
bb.note("No translations found for package " + pn)
}
do_build_opie_i18n () {
cd "${WORKDIR}/i18n" || die "ERROR:\nCouldn't find Opies i18n sources in ${PN}/i18n\nMake sure that <inherit opie_i18n> or <inherit opie> is *below* <SRC_URIS =>!"
if test -z "${I18N_FILES}"
then
package_name="`echo "${PN}"| sed "s/^opie\-//"`"
package_name2="`echo "${PN}"| sed "s/^opie\-//;s/\-//"`"
test "$package_name" != "$package_name2" && I18N_FILES="${package_name}.ts lib${package_name}.ts opie-${package_name}.ts ${package_name2}.ts lib${package_name2}.ts opie-${package_name2}.ts"
test "$package_name" = "$package_name2" && I18N_FILES="${package_name}.ts lib${package_name}.ts opie-${package_name}.ts"
echo -e "I18N Datafiles: ${I18N_FILES} (auto-detected)\nYou can overide the auto-detection by setting I18N_FILES in your .oe file"
else
echo "I18N Datafiles: ${I18N_FILES} (provided by .bb)"
fi
rm -f "${WORKDIR}/FILES.tmp" "${WORKDIR}/PACKAGES.tmp"
echo -e "\nFILES is set to [${FILES}]\n"
for file in ${I18N_FILES}
do
echo "Working on [$file]"
for ts_file in `ls -1 */*.ts | egrep "/$file"`
do
echo -e "\tCompiling [$ts_file]"
cd "${WORKDIR}/i18n/`dirname $ts_file`" || die "[${WORKDIR}/i18n/`dirname $ts_file`] not found"
opie-lrelease "`basename $ts_file`" || die "lrelease failed! Make sure that <inherit opie_i18n> or <inherit opie> is *below* <DEPENDS =>!"
# $lang is the language as in de_DE, $lang_sane replaces "_" with "-"
# to allow packaging as "_" is not allowed in a package name
lang="`echo "$ts_file" | sed -n "s#\(.*\)/\(.*\)#\1#p"`"
lang_sane="`echo "$ts_file" | sed -n "s#\(.*\)/\(.*\)#\1#p"|sed s/\_/\-/`"
echo -e "\tPackaging [`basename $ts_file`] for language [$lang]"
install -d ${D}${palmtopdir}/i18n/$lang
install -m 0644 ${WORKDIR}/i18n/$lang/.directory ${D}${palmtopdir}/i18n/$lang/
install -m 0644 ${WORKDIR}/i18n/$lang/*.qm "${D}${palmtopdir}/i18n/$lang/"
# As it is not possible to modify OE vars from within a _shell_ function,
# some major hacking was needed. These two files will be read by the python
# function do_build_opie_i18n_data() which sets the variables FILES_* and
# PACKAGES as needed.
echo -n "${PN}-${lang_sane} " >> "${WORKDIR}/PACKAGES.tmp"
echo -e "${PN}-${lang_sane}#${palmtopdir}/i18n/$lang" >> "${WORKDIR}/FILES.tmp"
ts_found_something=1
done
if test "$ts_found_something" != 1
then
echo -e "\tNo translations found"
else
ts_found_something=""
ts_found="$ts_found $file"
fi
# Only used for debugging purposes
test "${I18N_STATS}" = 1 && cd "${WORKDIR}/i18n"
echo -e "Completed [$file]\n\n"
done
qt_dirs="apps bin etc lib pics plugins share sounds"
for dir in $qt_dirs
do
dir_="$dir_ ${palmtopdir}/$dir "
done
# If we don't adjust FILES to exclude the i18n directory, we will end up with
# _lots_ of empty i18n/$lang directories in the original .ipk.
if (echo "${FILES}" | egrep "${palmtopdir}/? |${palmtopdir}/?$") &>/dev/null
then
echo "NOTE: FILES was set to ${palmtopdir} which would include the i18n directory"
echo -e "\n\nI'll remove ${palmtopdir} from FILES and replace it with all directories"
echo "below QtPalmtop, except i18n ($qt_dirs). See classes/opie_i18n.oeclass for details"
# Removes /opt/QtPalmtop from FILES but keeps /opt/QtPalmtop/$some_dir
FILES="`echo "$FILES"| sed "s#${palmtopdir}[/]\?\$\|${palmtopdir}[/]\? ##"`"
echo "${PN}#$FILES $dir_" >> "${WORKDIR}/FILES.tmp"
fi
# This is the common case for OPIE apps which are installed by opie.oeclass magic
if test -z "${FILES}"
then
echo "NOTE:"
echo -e "Since FILES is empty, i'll add all directories below ${palmtopdir} to it,\nexcluding i18n: ( $qt_dirs )"
echo "${PN}#$FILES $dir_" >> "${WORKDIR}/FILES.tmp"
fi
if ! test -e "${WORKDIR}/PACKAGES.tmp" -a "${I18N_STATS}" = 1
then
echo "No translations for package [${PN}]" >> /tmp/oe-i18n-missing.log
else
echo "Using [$ts_found ] for package [${PN}]" >> /tmp/oe-i18n.log
fi
# While this might not be very elegant, it safes a _ton_ of space (~30Mb) for
# each opie package.
for file in $(ls */*.ts | egrep -v "`echo "$ts_found"| sed "s/^\ //;s/\ /\|/"`")
do
rm "$file"
done
return 0
}
addtask build_opie_i18n before do_compile
addtask build_opie_i18n_data after do_build_opie_i18n before do_compile

View File

@@ -0,0 +1,598 @@
def legitimize_package_name(s):
return s.lower().replace('_', '-').replace('@', '+').replace(',', '+').replace('/', '-')
def do_split_packages(d, root, file_regex, output_pattern, description, postinst=None, recursive=False, hook=None, extra_depends=None, aux_files_pattern=None, postrm=None, allow_dirs=False, prepend=False, match_path=False):
import os, os.path, bb
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined")
return
packages = bb.data.getVar('PACKAGES', d, 1).split()
if not packages:
# nothing to do
return
if postinst:
postinst = '#!/bin/sh\n' + postinst + '\n'
if postrm:
postrm = '#!/bin/sh\n' + postrm + '\n'
if not recursive:
objs = os.listdir(dvar + root)
else:
objs = []
for walkroot, dirs, files in os.walk(dvar + root):
for file in files:
relpath = os.path.join(walkroot, file).replace(dvar + root + '/', '', 1)
if relpath:
objs.append(relpath)
if extra_depends == None:
extra_depends = bb.data.getVar('PKG_' + packages[0], d, 1) or packages[0]
for o in objs:
import re, stat
if match_path:
m = re.match(file_regex, o)
else:
m = re.match(file_regex, os.path.basename(o))
if not m:
continue
f = os.path.join(dvar + root, o)
mode = os.lstat(f).st_mode
if not (stat.S_ISREG(mode) or (allow_dirs and stat.S_ISDIR(mode))):
continue
on = legitimize_package_name(m.group(1))
pkg = output_pattern % on
if not pkg in packages:
if prepend:
packages = [pkg] + packages
else:
packages.append(pkg)
the_files = [os.path.join(root, o)]
if aux_files_pattern:
if type(aux_files_pattern) is list:
for fp in aux_files_pattern:
the_files.append(fp % on)
else:
the_files.append(aux_files_pattern % on)
bb.data.setVar('FILES_' + pkg, " ".join(the_files), d)
if extra_depends != '':
the_depends = bb.data.getVar('RDEPENDS_' + pkg, d, 1)
if the_depends:
the_depends = '%s %s' % (the_depends, extra_depends)
else:
the_depends = extra_depends
bb.data.setVar('RDEPENDS_' + pkg, the_depends, d)
bb.data.setVar('DESCRIPTION_' + pkg, description % on, d)
if postinst:
bb.data.setVar('pkg_postinst_' + pkg, postinst, d)
if postrm:
bb.data.setVar('pkg_postrm_' + pkg, postrm, d)
else:
oldfiles = bb.data.getVar('FILES_' + pkg, d, 1)
if not oldfiles:
bb.fatal("Package '%s' exists but has no files" % pkg)
bb.data.setVar('FILES_' + pkg, oldfiles + " " + os.path.join(root, o), d)
if callable(hook):
hook(f, pkg, file_regex, output_pattern, m.group(1))
bb.data.setVar('PACKAGES', ' '.join(packages), d)
python populate_packages () {
import glob, stat, errno, re
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined, unable to package")
return
import os # path manipulations
outdir = bb.data.getVar('DEPLOY_DIR', d, 1)
if not outdir:
bb.error("DEPLOY_DIR not defined, unable to package")
return
bb.mkdirhier(outdir)
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined, unable to package")
return
bb.mkdirhier(dvar)
packages = bb.data.getVar('PACKAGES', d, 1)
if not packages:
bb.debug(1, "PACKAGES not defined, nothing to package")
return
pn = bb.data.getVar('PN', d, 1)
if not pn:
bb.error("PN not defined")
return
os.chdir(dvar)
def isexec(path):
try:
s = os.stat(path)
except (os.error, AttributeError):
return 0
return (s[stat.ST_MODE] & stat.S_IEXEC)
for pkg in packages.split():
localdata = bb.data.createCopy(d)
root = os.path.join(workdir, "install", pkg)
os.system('rm -rf %s' % root)
bb.data.setVar('ROOT', '', localdata)
bb.data.setVar('ROOT_%s' % pkg, root, localdata)
pkgname = bb.data.getVar('PKG_%s' % pkg, localdata, 1)
if not pkgname:
pkgname = pkg
bb.data.setVar('PKG', pkgname, localdata)
overrides = bb.data.getVar('OVERRIDES', localdata, 1)
if not overrides:
raise bb.build.FuncFailed('OVERRIDES not defined')
bb.data.setVar('OVERRIDES', overrides+':'+pkg, localdata)
bb.data.update_data(localdata)
root = bb.data.getVar('ROOT', localdata, 1)
bb.mkdirhier(root)
filesvar = bb.data.getVar('FILES', localdata, 1) or ""
files = filesvar.split()
stripfunc = ""
for file in files:
if os.path.isabs(file):
file = '.' + file
if not os.path.islink(file):
if os.path.isdir(file):
newfiles = [ os.path.join(file,x) for x in os.listdir(file) ]
if newfiles:
files += newfiles
continue
globbed = glob.glob(file)
if globbed:
if [ file ] != globbed:
files += globbed
continue
if (not os.path.islink(file)) and (not os.path.exists(file)):
continue
fpath = os.path.join(root,file)
dpath = os.path.dirname(fpath)
bb.mkdirhier(dpath)
if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, 1) != '1') and not os.path.islink(file) and isexec(file):
stripfunc += "${STRIP} %s || : ;\n" % fpath
ret = bb.movefile(file,fpath)
if ret is None or ret == 0:
raise bb.build.FuncFailed("File population failed")
if not stripfunc == "":
from bb import build
# strip
bb.data.setVar('RUNSTRIP', '%s\nreturn 0' % stripfunc, localdata)
bb.data.setVarFlag('RUNSTRIP', 'func', 1, localdata)
bb.build.exec_func('RUNSTRIP', localdata)
del localdata
os.chdir(workdir)
unshipped = []
for root, dirs, files in os.walk(dvar):
for f in files:
path = os.path.join(root[len(dvar):], f)
unshipped.append(path)
if unshipped != []:
bb.note("the following files were installed but not shipped in any package:")
for f in unshipped:
bb.note(" " + f)
bb.build.exec_func("package_name_hook", d)
for pkg in packages.split():
if bb.data.getVar('PKG_%s' % pkg, d, 1) is None:
bb.data.setVar('PKG_%s' % pkg, pkg, d)
dangling_links = {}
pkg_files = {}
for pkg in packages.split():
dangling_links[pkg] = []
pkg_files[pkg] = []
inst_root = os.path.join(workdir, "install", pkg)
for root, dirs, files in os.walk(inst_root):
for f in files:
path = os.path.join(root, f)
rpath = path[len(inst_root):]
pkg_files[pkg].append(rpath)
try:
s = os.stat(path)
except OSError, (err, strerror):
if err != errno.ENOENT:
raise
target = os.readlink(path)
if target[0] != '/':
target = os.path.join(root[len(inst_root):], target)
dangling_links[pkg].append(os.path.normpath(target))
for pkg in packages.split():
rdepends = explode_deps(bb.data.getVar('RDEPENDS_' + pkg, d, 1) or bb.data.getVar('RDEPENDS', d, 1) or "")
for l in dangling_links[pkg]:
found = False
bb.debug(1, "%s contains dangling link %s" % (pkg, l))
for p in packages.split():
for f in pkg_files[p]:
if f == l:
found = True
bb.debug(1, "target found in %s" % p)
if p == pkg:
break
dp = bb.data.getVar('PKG_' + p, d, 1) or p
if not dp in rdepends:
rdepends.append(dp)
break
if found == False:
bb.note("%s contains dangling symlink to %s" % (pkg, l))
bb.data.setVar('RDEPENDS_' + pkg, " " + " ".join(rdepends), d)
def write_if_exists(f, pkg, var):
def encode(str):
import codecs
c = codecs.getencoder("string_escape")
return c(str)[0]
val = bb.data.getVar('%s_%s' % (var, pkg), d, 1)
if val:
f.write('%s_%s: %s\n' % (var, pkg, encode(val)))
data_file = os.path.join(workdir, "install", pn + ".package")
f = open(data_file, 'w')
f.write("PACKAGES: %s\n" % packages)
for pkg in packages.split():
write_if_exists(f, pkg, 'DESCRIPTION')
write_if_exists(f, pkg, 'RDEPENDS')
write_if_exists(f, pkg, 'RPROVIDES')
write_if_exists(f, pkg, 'PKG')
write_if_exists(f, pkg, 'ALLOW_EMPTY')
write_if_exists(f, pkg, 'FILES')
write_if_exists(f, pkg, 'pkg_postinst')
write_if_exists(f, pkg, 'pkg_postrm')
write_if_exists(f, pkg, 'pkg_preinst')
write_if_exists(f, pkg, 'pkg_prerm')
f.close()
bb.build.exec_func("read_subpackage_metadata", d)
}
ldconfig_postinst_fragment() {
if [ x"$D" = "x" ]; then
ldconfig
fi
}
python package_do_shlibs() {
import os, re, os.path
exclude_shlibs = bb.data.getVar('EXCLUDE_FROM_SHLIBS', d, 0)
if exclude_shlibs:
bb.note("not generating shlibs")
return
lib_re = re.compile("^lib.*\.so")
libdir_re = re.compile(".*/lib$")
packages = bb.data.getVar('PACKAGES', d, 1)
if not packages:
bb.debug(1, "no packages to build; not calculating shlibs")
return
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined")
return
staging = bb.data.getVar('STAGING_DIR', d, 1)
if not staging:
bb.error("STAGING_DIR not defined")
return
ver = bb.data.getVar('PV', d, 1)
if not ver:
bb.error("PV not defined")
return
target_sys = bb.data.getVar('TARGET_SYS', d, 1)
if not target_sys:
bb.error("TARGET_SYS not defined")
return
shlibs_dir = os.path.join(staging, target_sys, "shlibs")
old_shlibs_dir = os.path.join(staging, "shlibs")
bb.mkdirhier(shlibs_dir)
needed = {}
for pkg in packages.split():
needs_ldconfig = False
bb.debug(2, "calculating shlib provides for %s" % pkg)
pkgname = bb.data.getVar('PKG_%s' % pkg, d, 1)
if not pkgname:
pkgname = pkg
needed[pkg] = []
sonames = list()
top = os.path.join(workdir, "install", pkg)
for root, dirs, files in os.walk(top):
for file in files:
soname = None
path = os.path.join(root, file)
if os.access(path, os.X_OK) or lib_re.match(file):
cmd = (bb.data.getVar('BUILD_PREFIX', d, 1) or "") + "objdump -p " + path + " 2>/dev/null"
fd = os.popen(cmd)
lines = fd.readlines()
fd.close()
for l in lines:
m = re.match("\s+NEEDED\s+([^\s]*)", l)
if m:
needed[pkg].append(m.group(1))
m = re.match("\s+SONAME\s+([^\s]*)", l)
if m and not m.group(1) in sonames:
sonames.append(m.group(1))
if m and libdir_re.match(root):
needs_ldconfig = True
shlibs_file = os.path.join(shlibs_dir, pkgname + ".list")
if os.path.exists(shlibs_file):
os.remove(shlibs_file)
shver_file = os.path.join(shlibs_dir, pkgname + ".ver")
if os.path.exists(shver_file):
os.remove(shver_file)
if len(sonames):
fd = open(shlibs_file, 'w')
for s in sonames:
fd.write(s + '\n')
fd.close()
fd = open(shver_file, 'w')
fd.write(ver + '\n')
fd.close()
if needs_ldconfig:
bb.debug(1, 'adding ldconfig call to postinst for %s' % pkg)
postinst = bb.data.getVar('pkg_postinst_%s' % pkg, d, 1) or bb.data.getVar('pkg_postinst', d, 1)
if not postinst:
postinst = '#!/bin/sh\n'
postinst += bb.data.getVar('ldconfig_postinst_fragment', d, 1)
bb.data.setVar('pkg_postinst_%s' % pkg, postinst, d)
shlib_provider = {}
list_re = re.compile('^(.*)\.list$')
for dir in [old_shlibs_dir, shlibs_dir]:
if not os.path.exists(dir):
continue
for file in os.listdir(dir):
m = list_re.match(file)
if m:
dep_pkg = m.group(1)
fd = open(os.path.join(dir, file))
lines = fd.readlines()
fd.close()
ver_file = os.path.join(dir, dep_pkg + '.ver')
lib_ver = None
if os.path.exists(ver_file):
fd = open(ver_file)
lib_ver = fd.readline().rstrip()
fd.close()
for l in lines:
shlib_provider[l.rstrip()] = (dep_pkg, lib_ver)
for pkg in packages.split():
bb.debug(2, "calculating shlib requirements for %s" % pkg)
p_pkg = bb.data.getVar("PKG_%s" % pkg, d, 1) or pkg
deps = list()
for n in needed[pkg]:
if n in shlib_provider.keys():
(dep_pkg, ver_needed) = shlib_provider[n]
if dep_pkg == p_pkg:
continue
if ver_needed:
dep = "%s (>= %s)" % (dep_pkg, ver_needed)
else:
dep = dep_pkg
if not dep in deps:
deps.append(dep)
else:
bb.note("Couldn't find shared library provider for %s" % n)
deps_file = os.path.join(workdir, "install", pkg + ".shlibdeps")
if os.path.exists(deps_file):
os.remove(deps_file)
if len(deps):
fd = open(deps_file, 'w')
for dep in deps:
fd.write(dep + '\n')
fd.close()
}
python package_do_pkgconfig () {
import re, os
packages = bb.data.getVar('PACKAGES', d, 1)
if not packages:
bb.debug(1, "no packages to build; not calculating pkgconfig dependencies")
return
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined")
return
staging = bb.data.getVar('STAGING_DIR', d, 1)
if not staging:
bb.error("STAGING_DIR not defined")
return
target_sys = bb.data.getVar('TARGET_SYS', d, 1)
if not target_sys:
bb.error("TARGET_SYS not defined")
return
shlibs_dir = os.path.join(staging, target_sys, "shlibs")
old_shlibs_dir = os.path.join(staging, "shlibs")
bb.mkdirhier(shlibs_dir)
pc_re = re.compile('(.*)\.pc$')
var_re = re.compile('(.*)=(.*)')
field_re = re.compile('(.*): (.*)')
pkgconfig_provided = {}
pkgconfig_needed = {}
for pkg in packages.split():
pkgconfig_provided[pkg] = []
pkgconfig_needed[pkg] = []
top = os.path.join(workdir, "install", pkg)
for root, dirs, files in os.walk(top):
for file in files:
m = pc_re.match(file)
if m:
pd = bb.data.init()
name = m.group(1)
pkgconfig_provided[pkg].append(name)
path = os.path.join(root, file)
if not os.access(path, os.R_OK):
continue
f = open(path, 'r')
lines = f.readlines()
f.close()
for l in lines:
m = var_re.match(l)
if m:
name = m.group(1)
val = m.group(2)
bb.data.setVar(name, bb.data.expand(val, pd), pd)
continue
m = field_re.match(l)
if m:
hdr = m.group(1)
exp = bb.data.expand(m.group(2), pd)
if hdr == 'Requires':
pkgconfig_needed[pkg] += exp.replace(',', ' ').split()
for pkg in packages.split():
ppkg = bb.data.getVar("PKG_" + pkg, d, 1) or pkg
pkgs_file = os.path.join(shlibs_dir, ppkg + ".pclist")
if os.path.exists(pkgs_file):
os.remove(pkgs_file)
if pkgconfig_provided[pkg] != []:
f = open(pkgs_file, 'w')
for p in pkgconfig_provided[pkg]:
f.write('%s\n' % p)
f.close()
for dir in [old_shlibs_dir, shlibs_dir]:
if not os.path.exists(dir):
continue
for file in os.listdir(dir):
m = re.match('^(.*)\.pclist$', file)
if m:
pkg = m.group(1)
fd = open(os.path.join(dir, file))
lines = fd.readlines()
fd.close()
pkgconfig_provided[pkg] = []
for l in lines:
pkgconfig_provided[pkg].append(l.rstrip())
for pkg in packages.split():
deps = []
for n in pkgconfig_needed[pkg]:
found = False
for k in pkgconfig_provided.keys():
if n in pkgconfig_provided[k]:
if k != pkg and not (k in deps):
deps.append(k)
found = True
if found == False:
bb.note("couldn't find pkgconfig module '%s' in any package" % n)
deps_file = os.path.join(workdir, "install", pkg + ".pcdeps")
if os.path.exists(deps_file):
os.remove(deps_file)
if len(deps):
fd = open(deps_file, 'w')
for dep in deps:
fd.write(dep + '\n')
fd.close()
}
python package_do_split_locales() {
import os
if (bb.data.getVar('PACKAGE_NO_LOCALE', d, 1) == '1'):
bb.debug(1, "package requested not splitting locales")
return
packages = (bb.data.getVar('PACKAGES', d, 1) or "").split()
if not packages:
bb.debug(1, "no packages to build; not splitting locales")
return
datadir = bb.data.getVar('datadir', d, 1)
if not datadir:
bb.note("datadir not defined")
return
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined")
return
pn = bb.data.getVar('PN', d, 1)
if not pn:
bb.error("PN not defined")
return
if pn + '-locale' in packages:
packages.remove(pn + '-locale')
localedir = os.path.join(dvar + datadir, 'locale')
if not os.path.isdir(localedir):
bb.debug(1, "No locale files in this package")
return
locales = os.listdir(localedir)
mainpkg = packages[0]
for l in locales:
ln = legitimize_package_name(l)
pkg = pn + '-locale-' + ln
packages.append(pkg)
bb.data.setVar('FILES_' + pkg, os.path.join(datadir, 'locale', l), d)
bb.data.setVar('RDEPENDS_' + pkg, '${PKG_%s} virtual-locale-%s' % (mainpkg, ln), d)
bb.data.setVar('RPROVIDES_' + pkg, '%s-locale %s-translation' % (pn, ln), d)
bb.data.setVar('DESCRIPTION_' + pkg, '%s translation for %s' % (l, pn), d)
bb.data.setVar('PACKAGES', ' '.join(packages), d)
rdep = (bb.data.getVar('RDEPENDS_%s' % mainpkg, d, 1) or bb.data.getVar('RDEPENDS', d, 1) or "").split()
rdep.append('%s-locale*' % pn)
bb.data.setVar('RDEPENDS_%s' % mainpkg, ' '.join(rdep), d)
}
PACKAGEFUNCS = "do_install package_do_split_locales \
populate_packages package_do_shlibs \
package_do_pkgconfig read_shlibdeps"
python package_do_package () {
for f in (bb.data.getVar('PACKAGEFUNCS', d, 1) or '').split():
bb.build.exec_func(f, d)
}
do_package[dirs] = "${D}"
populate_packages[dirs] = "${D}"
EXPORT_FUNCTIONS do_package do_shlibs do_split_locales
addtask package before do_build after do_populate_staging

View File

@@ -0,0 +1,232 @@
inherit package
DEPENDS_prepend="${@["ipkg-utils-native ", ""][(bb.data.getVar('PACKAGES', d, 1) == '')]}"
BOOTSTRAP_EXTRA_RDEPENDS += "ipkg-collateral ipkg ipkg-link"
BOOTSTRAP_EXTRA_DEPENDS += "ipkg-collateral ipkg ipkg-link"
PACKAGEFUNCS += "do_package_ipk"
python package_ipk_fn () {
from bb import data
bb.data.setVar('PKGFN', bb.data.getVar('PKG',d), d)
}
python package_ipk_install () {
import os, sys
pkg = bb.data.getVar('PKG', d, 1)
pkgfn = bb.data.getVar('PKGFN', d, 1)
rootfs = bb.data.getVar('IMAGE_ROOTFS', d, 1)
ipkdir = bb.data.getVar('DEPLOY_DIR_IPK', d, 1)
stagingdir = bb.data.getVar('STAGING_DIR', d, 1)
tmpdir = bb.data.getVar('TMPDIR', d, 1)
if None in (pkg,pkgfn,rootfs):
raise bb.build.FuncFailed("missing variables (one or more of PKG, PKGFN, IMAGEROOTFS)")
try:
bb.mkdirhier(rootfs)
os.chdir(rootfs)
except OSError:
(type, value, traceback) = sys.exc_info()
print value
raise bb.build.FuncFailed
# Generate ipk.conf if it or the stamp doesnt exist
conffile = os.path.join(stagingdir,"ipkg.conf")
if not os.access(conffile, os.R_OK):
ipkg_archs = bb.data.getVar('IPKG_ARCHS',d)
if ipkg_archs is None:
bb.error("IPKG_ARCHS missing")
raise FuncFailed
ipkg_archs = ipkg_archs.split()
arch_priority = 1
f = open(conffile,"w")
for arch in ipkg_archs:
f.write("arch %s %s\n" % ( arch, arch_priority ))
arch_priority += 1
f.write("src local file:%s" % ipkdir)
f.close()
if (not os.access(os.path.join(ipkdir,"Packages"), os.R_OK) or
not os.access(os.path.join(os.path.join(tmpdir, "stamps"),"do_packages"),os.R_OK)):
ret = os.system('ipkg-make-index -p %s %s ' % (os.path.join(ipkdir, "Packages"), ipkdir))
if (ret != 0 ):
raise bb.build.FuncFailed
f=open(os.path.join(os.path.join(tmpdir, "stamps"),"do_packages"),"w")
f.close()
ret = os.system('ipkg-cl -o %s -f %s update' % (rootfs, conffile))
ret = os.system('ipkg-cl -o %s -f %s install %s' % (rootfs, conffile, pkgfn))
if (ret != 0 ):
raise bb.build.FuncFailed
}
python do_package_ipk () {
import copy # to back up env data
import sys
import re
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined, unable to package")
return
import os # path manipulations
outdir = bb.data.getVar('DEPLOY_DIR_IPK', d, 1)
if not outdir:
bb.error("DEPLOY_DIR_IPK not defined, unable to package")
return
bb.mkdirhier(outdir)
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined, unable to package")
return
bb.mkdirhier(dvar)
packages = bb.data.getVar('PACKAGES', d, 1)
if not packages:
bb.debug(1, "PACKAGES not defined, nothing to package")
return
tmpdir = bb.data.getVar('TMPDIR', d, 1)
# Invalidate the packages file
if os.access(os.path.join(os.path.join(tmpdir, "stamps"),"do_packages"),os.R_OK):
os.unlink(os.path.join(os.path.join(tmpdir, "stamps"),"do_packages"))
if packages == []:
bb.debug(1, "No packages; nothing to do")
return
for pkg in packages.split():
localdata = bb.data.createCopy(d)
root = "%s/install/%s" % (workdir, pkg)
bb.data.setVar('ROOT', '', localdata)
bb.data.setVar('ROOT_%s' % pkg, root, localdata)
pkgname = bb.data.getVar('PKG_%s' % pkg, localdata, 1)
if not pkgname:
pkgname = pkg
bb.data.setVar('PKG', pkgname, localdata)
overrides = bb.data.getVar('OVERRIDES', localdata)
if not overrides:
raise bb.build.FuncFailed('OVERRIDES not defined')
overrides = bb.data.expand(overrides, localdata)
bb.data.setVar('OVERRIDES', overrides + ':' + pkg, localdata)
bb.data.update_data(localdata)
basedir = os.path.join(os.path.dirname(root))
pkgoutdir = outdir
bb.mkdirhier(pkgoutdir)
os.chdir(root)
from glob import glob
g = glob('*')
try:
del g[g.index('CONTROL')]
del g[g.index('./CONTROL')]
except ValueError:
pass
if not g and not bb.data.getVar('ALLOW_EMPTY', localdata):
from bb import note
note("Not creating empty archive for %s-%s-%s" % (pkg, bb.data.getVar('PV', localdata, 1), bb.data.getVar('PR', localdata, 1)))
continue
controldir = os.path.join(root, 'CONTROL')
bb.mkdirhier(controldir)
try:
ctrlfile = file(os.path.join(controldir, 'control'), 'w')
except OSError:
raise bb.build.FuncFailed("unable to open control file for writing.")
fields = []
fields.append(["Version: %s-%s\n", ['PV', 'PR']])
fields.append(["Description: %s\n", ['DESCRIPTION']])
fields.append(["Section: %s\n", ['SECTION']])
fields.append(["Priority: %s\n", ['PRIORITY']])
fields.append(["Maintainer: %s\n", ['MAINTAINER']])
fields.append(["Architecture: %s\n", ['PACKAGE_ARCH']])
fields.append(["OE: %s\n", ['P']])
fields.append(["Homepage: %s\n", ['HOMEPAGE']])
def pullData(l, d):
l2 = []
for i in l:
l2.append(bb.data.getVar(i, d, 1))
return l2
ctrlfile.write("Package: %s\n" % pkgname)
# check for required fields
try:
for (c, fs) in fields:
for f in fs:
if bb.data.getVar(f, localdata) is None:
raise KeyError(f)
ctrlfile.write(c % tuple(pullData(fs, localdata)))
except KeyError:
(type, value, traceback) = sys.exc_info()
ctrlfile.close()
raise bb.build.FuncFailed("Missing field for ipk generation: %s" % value)
# more fields
rdepends = explode_deps(bb.data.getVar("RDEPENDS", localdata, 1) or "")
rrecommends = explode_deps(bb.data.getVar("RRECOMMENDS", localdata, 1) or "")
rsuggests = (bb.data.getVar("RSUGGESTS", localdata, 1) or "").split()
rprovides = (bb.data.getVar("RPROVIDES", localdata, 1) or "").split()
rreplaces = (bb.data.getVar("RREPLACES", localdata, 1) or "").split()
rconflicts = (bb.data.getVar("RCONFLICTS", localdata, 1) or "").split()
if rdepends:
ctrlfile.write("Depends: %s\n" % ", ".join(rdepends))
if rsuggests:
ctrlfile.write("Suggests: %s\n" % ", ".join(rsuggests))
if rrecommends:
ctrlfile.write("Recommends: %s\n" % ", ".join(rrecommends))
if rprovides:
ctrlfile.write("Provides: %s\n" % ", ".join(rprovides))
if rreplaces:
ctrlfile.write("Replaces: %s\n" % ", ".join(rreplaces))
if rconflicts:
ctrlfile.write("Conflicts: %s\n" % ", ".join(rconflicts))
src_uri = bb.data.getVar("SRC_URI", localdata, 1)
if src_uri:
src_uri = re.sub("\s+", " ", src_uri)
ctrlfile.write("Source: %s\n" % " ".join(src_uri.split()))
ctrlfile.close()
for script in ["preinst", "postinst", "prerm", "postrm"]:
scriptvar = bb.data.getVar('pkg_%s' % script, localdata, 1)
if not scriptvar:
continue
try:
scriptfile = file(os.path.join(controldir, script), 'w')
except OSError:
raise bb.build.FuncFailed("unable to open %s script file for writing." % script)
scriptfile.write(scriptvar)
scriptfile.close()
os.chmod(os.path.join(controldir, script), 0755)
conffiles_str = bb.data.getVar("CONFFILES", localdata, 1)
if conffiles_str:
try:
conffiles = file(os.path.join(controldir, 'conffiles'), 'w')
except OSError:
raise bb.build.FuncFailed("unable to open conffiles for writing.")
for f in conffiles_str.split():
conffiles.write('%s\n' % f)
conffiles.close()
os.chdir(basedir)
ret = os.system("PATH=\"%s\" %s %s %s" % (bb.data.getVar("PATH", localdata, 1),
bb.data.getVar("IPKGBUILDCMD",d,1), pkg, pkgoutdir))
if ret != 0:
raise bb.build.FuncFailed("ipkg-build execution failed")
for script in ["preinst", "postinst", "prerm", "postrm", "control" ]:
scriptfile = os.path.join(controldir, script)
try:
os.remove(scriptfile)
except OSError:
pass
try:
os.rmdir(controldir)
except OSError:
pass
del localdata
}

View File

@@ -0,0 +1,133 @@
inherit package
inherit rpm_core
RPMBUILD="rpmbuild --short-circuit ${RPMOPTS}"
PACKAGEFUNCS += "do_package_rpm"
python write_specfile() {
from bb import data, build
import sys
out_vartranslate = {
"PKG": "Name",
"PV": "Version",
"PR": "Release",
"DESCRIPTION": "%description",
"ROOT": "BuildRoot",
"LICENSE": "License",
"SECTION": "Group",
}
root = bb.data.getVar('ROOT', d)
# get %files
filesvar = bb.data.expand(bb.data.getVar('FILES', d), d) or ""
from glob import glob
files = filesvar.split()
todelete = []
for file in files:
if file[0] == '.':
newfile = file[1:]
files[files.index(file)] = newfile
file = newfile
else:
newfile = file
realfile = os.path.join(root, './'+file)
if not glob(realfile):
todelete.append(files[files.index(newfile)])
for r in todelete:
try:
del files[files.index(r)]
except ValueError:
pass
if not files:
from bb import note
note("Not creating empty archive for %s-%s-%s" % (bb.data.getVar('PKG',d, 1), bb.data.getVar('PV', d, 1), bb.data.getVar('PR', d, 1)))
return
# output .spec using this metadata store
try:
from __builtin__ import file
if not bb.data.getVar('OUTSPECFILE', d):
raise OSError('eek!')
specfile = file(bb.data.getVar('OUTSPECFILE', d), 'w')
except OSError:
raise bb.build.FuncFailed("unable to open spec file for writing.")
# fd = sys.__stdout__
fd = specfile
for var in out_vartranslate.keys():
if out_vartranslate[var][0] == "%":
continue
fd.write("%s\t: %s\n" % (out_vartranslate[var], bb.data.getVar(var, d)))
fd.write("Summary\t: .\n")
for var in out_vartranslate.keys():
if out_vartranslate[var][0] != "%":
continue
fd.write(out_vartranslate[var] + "\n")
fd.write(bb.data.getVar(var, d) + "\n\n")
fd.write("%files\n")
for file in files:
fd.write("%s\n" % file)
fd.close()
# call out rpm -bb on the .spec, thereby creating an rpm
bb.data.setVar('BUILDSPEC', "${RPMBUILD} -bb ${OUTSPECFILE}\n", d)
bb.data.setVarFlag('BUILDSPEC', 'func', '1', d)
bb.build.exec_func('BUILDSPEC', d)
# move the rpm into the pkgoutdir
rpm = bb.data.expand('${RPMBUILDPATH}/RPMS/${TARGET_ARCH}/${PKG}-${PV}-${PR}.${TARGET_ARCH}.rpm', d)
outrpm = bb.data.expand('${DEPLOY_DIR_RPM}/${PKG}-${PV}-${PR}.${TARGET_ARCH}.rpm', d)
bb.movefile(rpm, outrpm)
}
python do_package_rpm () {
workdir = bb.data.getVar('WORKDIR', d)
if not workdir:
raise bb.build.FuncFailed("WORKDIR not defined")
workdir = bb.data.expand(workdir, d)
import os # path manipulations
outdir = bb.data.getVar('DEPLOY_DIR_RPM', d)
if not outdir:
raise bb.build.FuncFailed("DEPLOY_DIR_RPM not defined")
outdir = bb.data.expand(outdir, d)
bb.mkdirhier(outdir)
packages = bb.data.getVar('PACKAGES', d)
if not packages:
packages = "${PN}"
bb.data.setVar('FILES', '', d)
ddir = bb.data.expand(bb.data.getVar('D', d), d)
bb.mkdirhier(ddir)
bb.data.setVar(bb.data.expand('FILES_${PN}', d), ''.join([ "./%s" % x for x in os.listdir(ddir)]), d)
packages = bb.data.expand(packages, d)
for pkg in packages.split():
localdata = bb.data.createCopy(d)
root = "%s/install/%s" % (workdir, pkg)
bb.data.setVar('ROOT', '', localdata)
bb.data.setVar('ROOT_%s' % pkg, root, localdata)
bb.data.setVar('PKG', pkg, localdata)
overrides = bb.data.getVar('OVERRIDES', localdata)
if not overrides:
raise bb.build.FuncFailed('OVERRIDES not defined')
overrides = bb.data.expand(overrides, localdata)
bb.data.setVar('OVERRIDES', '%s:%s' % (overrides, pkg), localdata)
bb.data.update_data(localdata)
# stuff
root = bb.data.getVar('ROOT', localdata)
basedir = os.path.dirname(root)
pkgoutdir = outdir
bb.mkdirhier(pkgoutdir)
bb.data.setVar('OUTSPECFILE', os.path.join(workdir, "%s.spec" % pkg), localdata)
bb.build.exec_func('write_specfile', localdata)
del localdata
}

View File

@@ -0,0 +1,99 @@
inherit package
PACKAGEFUNCS += "do_package_tar"
python package_tar_fn () {
import os
from bb import data
fn = os.path.join(bb.data.getVar('DEPLOY_DIR_TAR', d), "%s-%s-%s.tar.gz" % (bb.data.getVar('PKG', d), bb.data.getVar('PV', d), bb.data.getVar('PR', d)))
fn = bb.data.expand(fn, d)
bb.data.setVar('PKGFN', fn, d)
}
python package_tar_install () {
import os, sys
pkg = bb.data.getVar('PKG', d, 1)
pkgfn = bb.data.getVar('PKGFN', d, 1)
rootfs = bb.data.getVar('IMAGE_ROOTFS', d, 1)
if None in (pkg,pkgfn,rootfs):
bb.error("missing variables (one or more of PKG, PKGFN, IMAGEROOTFS)")
raise bb.build.FuncFailed
try:
bb.mkdirhier(rootfs)
os.chdir(rootfs)
except OSError:
(type, value, traceback) = sys.exc_info()
print value
raise bb.build.FuncFailed
if not os.access(pkgfn, os.R_OK):
bb.debug(1, "%s does not exist, skipping" % pkgfn)
raise bb.build.FuncFailed
ret = os.system('zcat %s | tar -xf -' % pkgfn)
if ret != 0:
raise bb.build.FuncFailed
}
python do_package_tar () {
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined, unable to package")
return
import os # path manipulations
outdir = bb.data.getVar('DEPLOY_DIR_TAR', d, 1)
if not outdir:
bb.error("DEPLOY_DIR_TAR not defined, unable to package")
return
bb.mkdirhier(outdir)
dvar = bb.data.getVar('D', d, 1)
if not dvar:
bb.error("D not defined, unable to package")
return
bb.mkdirhier(dvar)
packages = bb.data.getVar('PACKAGES', d, 1)
if not packages:
bb.debug(1, "PACKAGES not defined, nothing to package")
return
for pkg in packages.split():
localdata = bb.data.createCopy(d)
root = "%s/install/%s" % (workdir, pkg)
bb.data.setVar('ROOT', '', localdata)
bb.data.setVar('ROOT_%s' % pkg, root, localdata)
bb.data.setVar('PKG', pkg, localdata)
overrides = bb.data.getVar('OVERRIDES', localdata)
if not overrides:
raise bb.build.FuncFailed('OVERRIDES not defined')
overrides = bb.data.expand(overrides, localdata)
bb.data.setVar('OVERRIDES', '%s:%s' % (overrides, pkg), localdata)
bb.data.update_data(localdata)
# stuff
root = bb.data.getVar('ROOT', localdata)
bb.mkdirhier(root)
basedir = os.path.dirname(root)
pkgoutdir = outdir
bb.mkdirhier(pkgoutdir)
bb.build.exec_func('package_tar_fn', localdata)
tarfn = bb.data.getVar('PKGFN', localdata, 1)
# if os.path.exists(tarfn):
# del localdata
# continue
os.chdir(root)
from glob import glob
if not glob('*'):
bb.note("Not creating empty archive for %s-%s-%s" % (pkg, bb.data.getVar('PV', localdata, 1), bb.data.getVar('PR', localdata, 1)))
continue
ret = os.system("tar -czvf %s %s" % (tarfn, '.'))
if ret != 0:
bb.error("Creation of tar %s failed." % tarfn)
# end stuff
del localdata
}

View File

@@ -0,0 +1,10 @@
# basically a placeholder for something more fancy
# for now, just declare some things
inherit qmake
EXTRA_QMAKEVARS_POST_append = " DEFINES+=QWS LIBS+=-lqpe CONFIG+=qt LIBS-=-lstdc++ LIBS+=-lsupc++"
DEPENDS_prepend = "virtual/libqpe uicmoc-native "
FILES_${PN} = "${palmtopdir}"

View File

@@ -0,0 +1,7 @@
# Now that BitBake/OpenEmbedded uses Quilt by default, you can simply add an
# inherit patcher
# to one of your config files to let BB/OE use patcher again.
PATCHCLEANCMD = "patcher -B"
PATCHCMD = "patcher -R -p '%s' -n '%s' -i '%s'"
PATCH_DEPENDS = "${@["patcher-native", ""][(bb.data.getVar('PN', d, 1) == 'patcher-native')]}"

View File

@@ -0,0 +1,29 @@
PKG_DISTRIBUTECOMMAND[func] = "1"
python do_distribute_packages () {
cmd = bb.data.getVar('PKG_DISTRIBUTECOMMAND', d, 1)
if not cmd:
raise bb.build.FuncFailed("Unable to distribute packages, PKG_DISTRIBUTECOMMAND not defined")
bb.build.exec_func('PKG_DISTRIBUTECOMMAND', d)
}
addtask distribute_packages before do_build after do_fetch
PKG_DIST_LOCAL ?= "symlink"
PKG_DISTRIBUTEDIR ?= "${DEPLOY_DIR}/packages"
PKG_DISTRIBUTECOMMAND () {
p=`dirname ${FILE}`
d=`basename $p`
mkdir -p ${PKG_DISTRIBUTEDIR}
case "${PKG_DIST_LOCAL}" in
copy)
# use this weird tar command to copy because we want to
# exclude the BitKeeper directories
test -e ${PKG_DISTRIBUTEDIR}/${d} || mkdir ${PKG_DISTRIBUTEDIR}/${d};
(cd ${p}; tar -c --exclude SCCS -f - . ) | tar -C ${PKG_DISTRIBUTEDIR}/${d} -xpf -
;;
symlink)
ln -sf $p ${PKG_DISTRIBUTEDIR}/
;;
esac
}

View File

@@ -0,0 +1,22 @@
python do_pkg_write_metainfo () {
deploydir = bb.data.getVar('DEPLOY_DIR', d, 1)
if not deploydir:
bb.error("DEPLOY_DIR not defined, unable to write package info")
return
try:
infofile = file(os.path.join(deploydir, 'package-metainfo'), 'a')
except OSError:
raise bb.build.FuncFailed("unable to open package-info file for writing.")
name = bb.data.getVar('PN', d, 1)
version = bb.data.getVar('PV', d, 1)
desc = bb.data.getVar('DESCRIPTION', d, 1)
page = bb.data.getVar('HOMEPAGE', d, 1)
lic = bb.data.getVar('LICENSE', d, 1)
infofile.write("|| "+ name +" || "+ version + " || "+ desc +" || "+ page +" || "+ lic + " ||\n" )
infofile.close()
}
addtask pkg_write_metainfo after do_package before do_build

View File

@@ -0,0 +1,28 @@
inherit base
DEPENDS_prepend = "pkgconfig-native "
# The namespaces can clash here hence the two step replace
def get_pkgconfig_mangle(d):
import bb.data
s = "-e ''"
if not bb.data.inherits_class('native', d):
s += " -e 's:=${libdir}:=OELIBDIR:;'"
s += " -e 's:=${includedir}:=OEINCDIR:;'"
s += " -e 's:=${datadir}:=OEDATADIR:'"
s += " -e 's:=${prefix}:=OEPREFIX:'"
s += " -e 's:=${exec_prefix}:=OEEXECPREFIX:'"
s += " -e 's:OELIBDIR:${STAGING_LIBDIR}:;'"
s += " -e 's:OEINCDIR:${STAGING_INCDIR}:;'"
s += " -e 's:OEDATADIR:${STAGING_DATADIR}:'"
s += " -e 's:OEPREFIX:${STAGING_LIBDIR}/..:'"
s += " -e 's:OEEXECPREFIX:${STAGING_LIBDIR}/..:'"
return s
do_stage_append () {
for pc in `find ${S} -name '*.pc' | grep -v -- '-uninstalled.pc$'`; do
pcname=`basename $pc`
install -d ${PKG_CONFIG_PATH}
cat $pc | sed ${@get_pkgconfig_mangle(d)} > ${PKG_CONFIG_PATH}/$pcname
done
}

View File

@@ -0,0 +1,42 @@
DEPENDS_prepend = "qmake-native "
OE_QMAKE_PLATFORM = "${TARGET_OS}-oe-g++"
QMAKESPEC := "${QMAKE_MKSPEC_PATH}/${OE_QMAKE_PLATFORM}"
# We override this completely to eliminate the -e normally passed in
EXTRA_OEMAKE = ' MAKEFLAGS= '
export OE_QMAKE_CC="${CC}"
export OE_QMAKE_CFLAGS="${CFLAGS}"
export OE_QMAKE_CXX="${CXX}"
export OE_QMAKE_CXXFLAGS="-fno-exceptions -fno-rtti ${CXXFLAGS}"
export OE_QMAKE_LDFLAGS="${LDFLAGS}"
export OE_QMAKE_LINK="${CCLD}"
export OE_QMAKE_AR="${AR}"
export OE_QMAKE_STRIP="${STRIP}"
export OE_QMAKE_UIC="${STAGING_BINDIR}/uic"
export OE_QMAKE_MOC="${STAGING_BINDIR}/moc"
export OE_QMAKE_RPATH="-Wl,-rpath-link,"
# default to qte2 via bb.conf, inherit qt3x11 to configure for qt3x11
export OE_QMAKE_INCDIR_QT="${QTDIR}/include"
export OE_QMAKE_LIBDIR_QT="${QTDIR}/lib"
export OE_QMAKE_LIBS_QT="qte"
export OE_QMAKE_LIBS_X11=""
oe_qmake_mkspecs () {
mkdir -p mkspecs/${OE_QMAKE_PLATFORM}
for f in ${QMAKE_MKSPEC_PATH}/${OE_QMAKE_PLATFORM}/*; do
if [ -L $f ]; then
lnk=`readlink $f`
if [ -f mkspecs/${OE_QMAKE_PLATFORM}/$lnk ]; then
ln -s $lnk mkspecs/${OE_QMAKE_PLATFORM}/`basename $f`
else
cp $f mkspecs/${OE_QMAKE_PLATFORM}/
fi
else
cp $f mkspecs/${OE_QMAKE_PLATFORM}/
fi
done
}

View File

@@ -0,0 +1,57 @@
inherit qmake-base
qmake_do_configure() {
case ${QMAKESPEC} in
*linux-oe-g++|*linux-uclibc-oe-g++)
;;
*-oe-g++)
die Unsupported target ${TARGET_OS} for oe-g++ qmake spec
;;
*)
oenote Searching for qmake spec file
paths="${QMAKE_MKSPEC_PATH}/qws/${TARGET_OS}-${TARGET_ARCH}-g++"
paths="${QMAKE_MKSPEC_PATH}/${TARGET_OS}-g++ $paths"
if (echo "${TARGET_ARCH}"|grep -q 'i.86'); then
paths="${QMAKE_MKSPEC_PATH}/qws/${TARGET_OS}-x86-g++ $paths"
fi
for i in $paths; do
if test -e $i; then
export QMAKESPEC=$i
break
fi
done
;;
esac
oenote "using qmake spec in ${QMAKESPEC}, using profiles '${QMAKE_PROFILES}'"
if [ -z "${QMAKE_PROFILES}" ]; then
PROFILES="`ls *.pro`"
else
PROFILES="${QMAKE_PROFILES}"
fi
if [ -z "$PROFILES" ]; then
die "QMAKE_PROFILES not set and no profiles found in $PWD"
fi
if [ ! -z "${EXTRA_QMAKEVARS_POST}" ]; then
AFTER="-after"
QMAKE_VARSUBST_POST="${EXTRA_QMAKEVARS_POST}"
oenote "qmake postvar substitution: ${EXTRA_QMAKEVARS_POST}"
fi
if [ ! -z "${EXTRA_QMAKEVARS_PRE}" ]; then
QMAKE_VARSUBST_PRE="${EXTRA_QMAKEVARS_PRE}"
oenote "qmake prevar substitution: ${EXTRA_QMAKEVARS_PRE}"
fi
#oenote "Calling 'qmake -makefile -spec ${QMAKESPEC} -o Makefile $QMAKE_VARSUBST_PRE $AFTER $PROFILES $QMAKE_VARSUBST_POST'"
unset QMAKESPEC || true
qmake -makefile -spec ${QMAKESPEC} -o Makefile $QMAKE_VARSUBST_PRE $AFTER $PROFILES $QMAKE_VARSUBST_POST || die "Error calling qmake on $PROFILES"
}
EXPORT_FUNCTIONS do_configure
addtask configure after do_unpack do_patch before do_compile

View File

@@ -0,0 +1,36 @@
PACKAGE_ARCH = "all"
do_configure() {
:
}
do_compile() {
:
}
pkg_postinst_fonts() {
#!/bin/sh
set -e
. /etc/profile
${sbindir}/update-qtfontdir
}
pkg_postrm_fonts() {
#!/bin/sh
set -e
. /etc/profile
${sbindir}/update-qtfontdir -f
}
python populate_packages_prepend() {
postinst = bb.data.getVar('pkg_postinst_fonts', d, 1)
postrm = bb.data.getVar('pkg_postrm_fonts', d, 1)
fontdir = bb.data.getVar('palmtopdir', d, 1) + '/lib/fonts'
pkgregex = "^([a-z-]*_[0-9]*).*.qpf$"
pkgpattern = bb.data.getVar('QPF_PKGPATTERN', d, 1) or 'qpf-%s'
pkgdescription = bb.data.getVar('QPF_DESCRIPTION', d, 1) or 'QPF font %s'
do_split_packages(d, root=fontdir, file_regex=pkgregex, output_pattern=pkgpattern,
description=pkgdescription, postinst=postinst, postrm=postrm, recursive=True, hook=None,
extra_depends='qpf-font-common')
}

View File

@@ -0,0 +1,11 @@
#
# override variables set by qmake-base to compile Qt/X11 apps
#
export QTDIR="${STAGING_DIR}/${HOST_SYS}/qte3"
export QTEDIR="${STAGING_DIR}/${HOST_SYS}/qte3"
export OE_QMAKE_UIC="${STAGING_BINDIR}/uic3"
export OE_QMAKE_MOC="${STAGING_BINDIR}/moc3"
export OE_QMAKE_CXXFLAGS="${CXXFLAGS} "
export OE_QMAKE_INCDIR_QT="${QTEDIR}/include"
export OE_QMAKE_LIBDIR_QT="${QTEDIR}/lib"
export OE_QMAKE_LIBS_QT="qte"

View File

@@ -0,0 +1,11 @@
#
# override variables set by qmake-base to compile Qt/X11 apps
#
export QTDIR="${STAGING_DIR}/${HOST_SYS}/qt3"
export OE_QMAKE_UIC="${STAGING_BINDIR}/uic3"
export OE_QMAKE_MOC="${STAGING_BINDIR}/moc3"
export OE_QMAKE_CXXFLAGS="${CXXFLAGS} -DQT_NO_XIM"
export OE_QMAKE_INCDIR_QT="${QTDIR}/include"
export OE_QMAKE_LIBDIR_QT="${QTDIR}/lib"
export OE_QMAKE_LIBS_QT="qt"
export OE_QMAKE_LIBS_X11="-lXext -lX11 -lm"

View File

@@ -0,0 +1,11 @@
#
# override variables set by qmake-base to compile Qt/X11 apps
#
export QTDIR="${STAGING_DIR}/${HOST_SYS}/qt4"
export OE_QMAKE_UIC="${STAGING_BINDIR}/uic4"
export OE_QMAKE_MOC="${STAGING_BINDIR}/moc4"
export OE_QMAKE_CXXFLAGS="${CXXFLAGS}"
export OE_QMAKE_INCDIR_QT="${QTDIR}/include"
export OE_QMAKE_LIBDIR_QT="${QTDIR}/lib"
export OE_QMAKE_LIBS_QT="qt"
export OE_QMAKE_LIBS_X11="-lXext -lX11 -lm"

View File

@@ -0,0 +1,22 @@
#
# Removes source after build
#
# To use it add that line to conf/local.conf:
#
# INHERIT += "rm_work"
#
do_rm_work () {
cd ${WORKDIR}
for dir in *
do
if [ `basename ${S}` == $dir ]; then
rm -rf $dir/*
elif [ $dir != 'temp' ]; then
rm -rf $dir
fi
done
}
addtask rm_work before do_build
addtask rm_work after do_package

View File

@@ -0,0 +1,145 @@
#
# Creates a root filesystem out of IPKs
#
# This rootfs can be mounted via root-nfs or it can be put into an cramfs/jffs etc.
# See image_ipk.oeclass for a usage of this.
#
DEPENDS_prepend="ipkg-native ipkg-utils-native fakeroot-native "
DEPENDS_append=" ${EXTRA_IMAGEDEPENDS}"
PACKAGES = ""
do_rootfs[nostamp] = 1
do_rootfs[dirs] = ${TOPDIR}
do_build[nostamp] = 1
IPKG_ARGS = "-f ${T}/ipkg.conf -o ${IMAGE_ROOTFS}"
ROOTFS_POSTPROCESS_COMMAND ?= ""
PID = "${@os.getpid()}"
# some default locales
IMAGE_LINGUAS ?= "de-de fr-fr en-gb"
LINGUAS_INSTALL = "${@" ".join(map(lambda s: "locale-base-%s" % s, bb.data.getVar('IMAGE_LINGUAS', d, 1).split()))}"
real_do_rootfs () {
set -x
mkdir -p ${IMAGE_ROOTFS}/dev
if [ -z "${DEPLOY_KEEP_PACKAGES}" ]; then
rm -f ${DEPLOY_DIR_IPK}/Packages
touch ${DEPLOY_DIR_IPK}/Packages
ipkg-make-index -r ${DEPLOY_DIR_IPK}/Packages -p ${DEPLOY_DIR_IPK}/Packages -l ${DEPLOY_DIR_IPK}/Packages.filelist -m ${DEPLOY_DIR_IPK}
fi
mkdir -p ${T}
echo "src oe file:${DEPLOY_DIR_IPK}" > ${T}/ipkg.conf
ipkgarchs="all any noarch ${TARGET_ARCH} ${IPKG_ARCHS} ${MACHINE}"
priority=1
for arch in $ipkgarchs; do
echo "arch $arch $priority" >> ${T}/ipkg.conf
priority=$(expr $priority + 5)
done
ipkg-cl ${IPKG_ARGS} update
if [ ! -z "${LINGUAS_INSTALL}" ]; then
ipkg-cl ${IPKG_ARGS} install glibc-localedata-i18n
for i in ${LINGUAS_INSTALL}; do
ipkg-cl ${IPKG_ARGS} install $i
done
fi
if [ ! -z "${IPKG_INSTALL}" ]; then
ipkg-cl ${IPKG_ARGS} install ${IPKG_INSTALL}
fi
export D=${IMAGE_ROOTFS}
export IPKG_OFFLINE_ROOT=${IMAGE_ROOTFS}
mkdir -p ${IMAGE_ROOTFS}/etc/ipkg/
grep "^arch" ${T}/ipkg.conf >${IMAGE_ROOTFS}/etc/ipkg/arch.conf
for i in ${IMAGE_ROOTFS}${libdir}/ipkg/info/*.preinst; do
if [ -f $i ] && ! sh $i; then
ipkg-cl ${IPKG_ARGS} flag unpacked `basename $i .preinst`
fi
done
for i in ${IMAGE_ROOTFS}${libdir}/ipkg/info/*.postinst; do
if [ -f $i ] && ! sh $i configure; then
ipkg-cl ${IPKG_ARGS} flag unpacked `basename $i .postinst`
fi
done
install -d ${IMAGE_ROOTFS}/${sysconfdir}
echo ${BUILDNAME} > ${IMAGE_ROOTFS}/${sysconfdir}/version
${ROOTFS_POSTPROCESS_COMMAND}
log_check rootfs
}
log_check() {
set +x
for target in $*
do
lf_path="${WORKDIR}/temp/log.do_$target.${PID}"
echo "log_check: Using $lf_path as logfile"
if test -e "$lf_path"
then
lf_txt="`cat $lf_path`"
for keyword_die in "Cannot find package" "exit 1" ERR Fail
do
if (echo "$lf_txt" | grep -v log_check | grep "$keyword_die") &>/dev/null
then
echo "log_check: There were error messages in the logfile"
echo -e "log_check: Matched keyword: [$keyword_die]\n"
echo "$lf_txt" | grep -v log_check | grep -i "$keyword_die"
echo ""
do_exit=1
fi
done
test "$do_exit" = 1 && exit 1
else
echo "Cannot find logfile [$lf_path]"
fi
echo "Logfile is clean"
done
set -x
}
fakeroot do_rootfs () {
rm -rf ${IMAGE_ROOTFS}
real_do_rootfs
}
# set '*' as the rootpassword so the images
# can decide if they want it or not
zap_root_password () {
sed 's%^root:[^:]*:%root:*:%' < ${IMAGE_ROOTFS}/etc/passwd >${IMAGE_ROOTFS}/etc/passwd.new
mv ${IMAGE_ROOTFS}/etc/passwd.new ${IMAGE_ROOTFS}/etc/passwd
}
create_etc_timestamp() {
date +%2m%2d%2H%2M%Y >${IMAGE_ROOTFS}/etc/timestamp
}
# Turn any symbolic /sbin/init link into a file
remove_init_link () {
if [ -h ${IMAGE_ROOTFS}/sbin/init ]; then
LINKFILE=${IMAGE_ROOTFS}`readlink ${IMAGE_ROOTFS}/sbin/init`
rm ${IMAGE_ROOTFS}/sbin/init
cp $LINKFILE ${IMAGE_ROOTFS}/sbin/init
fi
}
# export the zap_root_password, create_etc_timestamp and remote_init_link
EXPORT_FUNCTIONS zap_root_password create_etc_timestamp remove_init_link
addtask rootfs before do_build after do_install

View File

@@ -0,0 +1,16 @@
RPMBUILDPATH="${WORKDIR}/rpm"
RPMOPTS="--rcfile=${WORKDIR}/rpmrc"
RPMOPTS="--rcfile=${WORKDIR}/rpmrc --target ${TARGET_SYS}"
RPM="rpm ${RPMOPTS}"
RPMBUILD="rpmbuild --buildroot ${D} --short-circuit ${RPMOPTS}"
rpm_core_do_preprpm() {
mkdir -p ${RPMBUILDPATH}/{SPECS,RPMS/{i386,i586,i686,noarch,ppc,mips,mipsel,arm},SRPMS,SOURCES,BUILD}
echo 'macrofiles:/usr/lib/rpm/macros:${WORKDIR}/macros' > ${WORKDIR}/rpmrc
echo '%_topdir ${RPMBUILDPATH}' > ${WORKDIR}/macros
echo '%_repackage_dir ${WORKDIR}' >> ${WORKDIR}/macros
}
EXPORT_FUNCTIONS do_preprpm
addtask preprpm before do_fetch

View File

@@ -0,0 +1,13 @@
DEPENDS += "python-scons-native"
scons_do_compile() {
${STAGING_BINDIR}/scons || \
oefatal "scons build execution failed."
}
scons_do_install() {
${STAGING_BINDIR}/scons install || \
oefatal "scons install execution failed."
}
EXPORT_FUNCTIONS do_compile do_install

View File

@@ -0,0 +1,22 @@
# SDK packages are built either explicitly by the user,
# or indirectly via dependency. No need to be in 'world'.
EXCLUDE_FROM_WORLD = "1"
SDK_NAME = "${TARGET_ARCH}/oe"
PACKAGE_ARCH = "${BUILD_ARCH}"
HOST_ARCH = "${BUILD_ARCH}"
HOST_VENDOR = "${BUILD_VENDOR}"
HOST_OS = "${BUILD_OS}"
HOST_PREFIX = "${BUILD_PREFIX}"
HOST_CC_ARCH = "${BUILD_CC_ARCH}"
export CPPFLAGS = "${BUILD_CPPFLAGS}"
export CFLAGS = "${BUILD_CFLAGS}"
export CXXFLAGS = "${BUILD_CFLAGS}"
export LDFLAGS = "${BUILD_LDFLAGS}"
prefix = "/usr/local/${SDK_NAME}"
exec_prefix = "${prefix}"
FILES_${PN} = "${prefix}"

View File

@@ -0,0 +1,27 @@
FILES_${PN} += '${libdir}/perl5'
sdl_do_configure () {
if [ -x ${S}/configure ] ; then
cfgcmd="${S}/configure \
-GL -GLU"
oenote "Running $cfgcmd..."
$cfgcmd || oefatal "oe_runconf failed"
if [ "${BUILD_SYS}" != "${HOST_SYS}" ]; then
. ${STAGING_DIR}/${TARGET_SYS}/perl/config.sh
sed -e "s:\(SITELIBEXP = \).*:\1${sitelibexp}:; s:\(SITEARCHEXP = \).*:\1${sitearchexp}:; s:\(INSTALLVENDORLIB = \).*:\1${D}${libdir}/perl5:; s:\(INSTALLVENDORARCH = \).*:\1${D}${libdir}/perl5:" < Makefile > Makefile.new
mv Makefile.new Makefile
fi
else
oefatal "no configure script found"
fi
}
sdl_do_compile () {
oe_runmake PASTHRU_INC="${CFLAGS}"
}
sdl_do_install () {
oe_runmake install_vendor
}
EXPORT_FUNCTIONS do_configure do_compile do_install

View File

@@ -0,0 +1,53 @@
DEPENDS_prepend = "sip-native python-sip "
#EXTRA_SIPTAGS = "-tWS_QWS -tQtPE_1_6_0 -tQt_2_3_1"
sip_do_generate() {
if [ -z "${SIP_MODULES}" ]; then
MODULES="`ls sip/*mod.sip`"
else
MODULES="${SIP_MODULES}"
fi
if [ -z "$MODULES" ]; then
die "SIP_MODULES not set and no modules found in $PWD"
else
oenote "using modules '${SIP_MODULES}' and tags '${EXTRA_SIPTAGS}'"
fi
if [ -z "${EXTRA_SIPTAGS}" ]; then
die "EXTRA_SIPTAGS needs to be set!"
else
SIPTAGS="${EXTRA_SIPTAGS}"
fi
if [ ! -z "${SIP_FEATURES}" ]; then
FEATURES="-z ${SIP_FEATURES}"
oenote "sip feature file: ${SIP_FEATURES}"
fi
for module in $MODULES
do
install -d ${module}/
oenote "calling 'sip -I sip -I ${STAGING_SIPDIR} ${SIPTAGS} ${FEATURES} -c ${module} -b ${module}/${module}.pro.in sip/${module}/${module}mod.sip'"
sip -I ${STAGING_SIPDIR} -I sip ${SIPTAGS} ${FEATURES} -c ${module} -b ${module}/${module}.sbf sip/${module}/${module}mod.sip \
|| die "Error calling sip on ${module}"
cat ${module}/${module}.sbf | sed s,target,TARGET, \
| sed s,sources,SOURCES, \
| sed s,headers,HEADERS, \
| sed s,"moc_HEADERS =","HEADERS +=", \
>${module}/${module}.pro
echo "TEMPLATE=lib" >>${module}/${module}.pro
[ "${module}" = "qt" ] && echo "" >>${module}/${module}.pro
[ "${module}" = "qtcanvas" ] && echo "" >>${module}/${module}.pro
[ "${module}" = "qttable" ] && echo "" >>${module}/${module}.pro
[ "${module}" = "qwt" ] && echo "" >>${module}/${module}.pro
[ "${module}" = "qtpe" ] && echo "" >>${module}/${module}.pro
[ "${module}" = "qtpe" ] && echo "LIBS+=-lqpe" >>${module}/${module}.pro
true
done
}
EXPORT_FUNCTIONS do_generate
addtask generate after do_unpack do_patch before do_configure

View File

@@ -0,0 +1,111 @@
DEPLOY_DIR_SRC ?= "${DEPLOY_DIR}/source"
EXCLUDE_FROM ?= ".pc autom4te.cache"
# used as part of a path. make sure it's set
DISTRO ?= "openembedded"
def get_src_tree(d):
import bb
import os, os.path
workdir = bb.data.getVar('WORKDIR', d, 1)
if not workdir:
bb.error("WORKDIR not defined, unable to find source tree.")
return
s = bb.data.getVar('S', d, 0)
if not s:
bb.error("S not defined, unable to find source tree.")
return
s_tree_raw = s.split('/')[1]
s_tree = bb.data.expand(s_tree_raw, d)
src_tree_path = os.path.join(workdir, s_tree)
try:
os.listdir(src_tree_path)
except OSError:
bb.fatal("Expected to find source tree in '%s' which doesn't exist." % src_tree_path)
bb.debug("Assuming source tree is '%s'" % src_tree_path)
return s_tree
sourcepkg_do_create_orig_tgz(){
mkdir -p ${DEPLOY_DIR_SRC}
cd ${WORKDIR}
for i in ${EXCLUDE_FROM}; do
echo $i >> temp/exclude-from-file
done
src_tree=${@get_src_tree(d)}
echo $src_tree
oenote "Creating .orig.tar.gz in ${DEPLOY_DIR_SRC}/${P}.orig.tar.gz"
tar cvzf ${DEPLOY_DIR_SRC}/${P}.orig.tar.gz --exclude-from temp/exclude-from-file $src_tree
cp -pPR $src_tree $src_tree.orig
}
sourcepkg_do_archive_bb() {
src_tree=${@get_src_tree(d)}
dest=${WORKDIR}/$src_tree/${DISTRO}
mkdir -p $dest
cp ${FILE} $dest
}
python sourcepkg_do_dumpdata() {
import os
import os.path
workdir = bb.data.getVar('WORKDIR', d, 1)
distro = bb.data.getVar('DISTRO', d, 1)
s_tree = get_src_tree(d)
openembeddeddir = os.path.join(workdir, s_tree, distro)
dumpfile = os.path.join(openembeddeddir, bb.data.expand("${P}-${PR}.showdata.dump",d))
try:
os.mkdir(openembeddeddir)
except OSError:
# dir exists
pass
bb.note("Dumping metadata into '%s'" % dumpfile)
f = open(dumpfile, "w")
# emit variables and shell functions
bb.data.emit_env(f, d, True)
# emit the metadata which isnt valid shell
for e in d.keys():
if bb.data.getVarFlag(e, 'python', d):
f.write("\npython %s () {\n%s}\n" % (e, bb.data.getVar(e, d, 1)))
f.close()
}
sourcepkg_do_create_diff_gz(){
cd ${WORKDIR}
for i in ${EXCLUDE_FROM}; do
echo $i >> temp/exclude-from-file
done
src_tree=${@get_src_tree(d)}
for i in `find . -maxdepth 1 -type f`; do
mkdir -p $src_tree/${DISTRO}/files
cp $i $src_tree/${DISTRO}/files
done
oenote "Creating .diff.gz in ${DEPLOY_DIR_SRC}/${P}-${PR}.diff.gz"
LC_ALL=C TZ=UTC0 diff --exclude-from=temp/exclude-from-file -Naur $src_tree.orig $src_tree | gzip -c > ${DEPLOY_DIR_SRC}/${P}-${PR}.diff.gz
rm -rf $src_tree.orig
}
EXPORT_FUNCTIONS do_create_orig_tgz do_archive_bb do_dumpdata do_create_diff_gz
addtask create_orig_tgz after do_unpack before do_patch
addtask archive_bb after do_patch before do_dumpdata
addtask dumpdata after archive_bb before do_create_diff_gz
addtask create_diff_gz after do_dump_data before do_configure

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