summaryrefslogtreecommitdiffstats
path: root/import-layers/yocto-poky/meta/lib/oe/recipeutils.py
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/meta/lib/oe/recipeutils.py')
-rw-r--r--import-layers/yocto-poky/meta/lib/oe/recipeutils.py170
1 files changed, 128 insertions, 42 deletions
diff --git a/import-layers/yocto-poky/meta/lib/oe/recipeutils.py b/import-layers/yocto-poky/meta/lib/oe/recipeutils.py
index 6c7adb5bd..58e4028ae 100644
--- a/import-layers/yocto-poky/meta/lib/oe/recipeutils.py
+++ b/import-layers/yocto-poky/meta/lib/oe/recipeutils.py
@@ -2,7 +2,7 @@
#
# Some code borrowed from the OE layer index
#
-# Copyright (C) 2013-2015 Intel Corporation
+# Copyright (C) 2013-2016 Intel Corporation
#
import sys
@@ -11,31 +11,32 @@ import os.path
import tempfile
import textwrap
import difflib
-import utils
+from . import utils
import shutil
import re
import fnmatch
+import glob
from collections import OrderedDict, defaultdict
# Help us to find places to insert values
-recipe_progression = ['SUMMARY', 'DESCRIPTION', 'HOMEPAGE', 'BUGTRACKER', 'SECTION', 'LICENSE', 'LIC_FILES_CHKSUM', 'PROVIDES', 'DEPENDS', 'PR', 'PV', 'SRCREV', 'SRC_URI', 'S', 'do_fetch()', 'do_unpack()', 'do_patch()', 'EXTRA_OECONF', 'do_configure()', 'EXTRA_OEMAKE', 'do_compile()', 'do_install()', 'do_populate_sysroot()', 'INITSCRIPT', 'USERADD', 'GROUPADD', 'PACKAGES', 'FILES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RPROVIDES', 'RREPLACES', 'RCONFLICTS', 'ALLOW_EMPTY', 'do_package()', 'do_deploy()']
+recipe_progression = ['SUMMARY', 'DESCRIPTION', 'HOMEPAGE', 'BUGTRACKER', 'SECTION', 'LICENSE', 'LICENSE_FLAGS', 'LIC_FILES_CHKSUM', 'PROVIDES', 'DEPENDS', 'PR', 'PV', 'SRCREV', 'SRCPV', 'SRC_URI', 'S', 'do_fetch()', 'do_unpack()', 'do_patch()', 'EXTRA_OECONF', 'EXTRA_OECMAKE', 'EXTRA_OESCONS', 'do_configure()', 'EXTRA_OEMAKE', 'do_compile()', 'do_install()', 'do_populate_sysroot()', 'INITSCRIPT', 'USERADD', 'GROUPADD', 'PACKAGES', 'FILES', 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RPROVIDES', 'RREPLACES', 'RCONFLICTS', 'ALLOW_EMPTY', 'populate_packages()', 'do_package()', 'do_deploy()']
# Variables that sometimes are a bit long but shouldn't be wrapped
nowrap_vars = ['SUMMARY', 'HOMEPAGE', 'BUGTRACKER', 'SRC_URI[md5sum]', 'SRC_URI[sha256sum]']
list_vars = ['SRC_URI', 'LIC_FILES_CHKSUM']
meta_vars = ['SUMMARY', 'DESCRIPTION', 'HOMEPAGE', 'BUGTRACKER', 'SECTION']
-def pn_to_recipe(cooker, pn):
+def pn_to_recipe(cooker, pn, mc=''):
"""Convert a recipe name (PN) to the path to the recipe file"""
import bb.providers
- if pn in cooker.recipecache.pkg_pn:
- best = bb.providers.findBestProvider(pn, cooker.data, cooker.recipecache, cooker.recipecache.pkg_pn)
+ if pn in cooker.recipecaches[mc].pkg_pn:
+ best = bb.providers.findBestProvider(pn, cooker.data, cooker.recipecaches[mc], cooker.recipecaches[mc].pkg_pn)
return best[3]
- elif pn in cooker.recipecache.providers:
- filenames = cooker.recipecache.providers[pn]
- eligible, foundUnique = bb.providers.filterProviders(filenames, pn, cooker.expanded_data, cooker.recipecache)
+ elif pn in cooker.recipecaches[mc].providers:
+ filenames = cooker.recipecaches[mc].providers[pn]
+ eligible, foundUnique = bb.providers.filterProviders(filenames, pn, cooker.expanded_data, cooker.recipecaches[mc])
filename = eligible[0]
return filename
else:
@@ -49,13 +50,14 @@ def get_unavailable_reasons(cooker, pn):
return taskdata.get_reasons(pn)
-def parse_recipe(fn, appendfiles, d):
+def parse_recipe(cooker, fn, appendfiles):
"""
Parse an individual recipe file, optionally with a list of
bbappend files.
"""
import bb.cache
- envdata = bb.cache.Cache.loadDataFull(fn, appendfiles, d)
+ parser = bb.cache.NoCache(cooker.databuilder)
+ envdata = parser.loadDataFull(fn, appendfiles)
return envdata
@@ -78,7 +80,7 @@ def parse_recipe_simple(cooker, pn, d, appends=True):
appendfiles = cooker.collection.get_file_appends(recipefile)
else:
appendfiles = None
- return parse_recipe(recipefile, appendfiles, d)
+ return parse_recipe(cooker, recipefile, appendfiles)
def get_var_files(fn, varlist, d):
@@ -158,15 +160,19 @@ def split_var_value(value, assignment=True):
return outlist
-def patch_recipe_file(fn, values, patch=False, relpath=''):
- """Update or insert variable values into a recipe file (assuming you
- have already identified the exact file you want to update.)
+def patch_recipe_lines(fromlines, values, trailing_newline=True):
+ """Update or insert variable values into lines from a recipe.
Note that some manual inspection/intervention may be required
since this cannot handle all situations.
"""
import bb.utils
+ if trailing_newline:
+ newline = '\n'
+ else:
+ newline = ''
+
recipe_progression_res = []
recipe_progression_restrs = []
for item in recipe_progression:
@@ -190,14 +196,14 @@ def patch_recipe_file(fn, values, patch=False, relpath=''):
remainingnames = {}
for k in values.keys():
remainingnames[k] = get_recipe_pos(k)
- remainingnames = OrderedDict(sorted(remainingnames.iteritems(), key=lambda x: x[1]))
+ remainingnames = OrderedDict(sorted(remainingnames.items(), key=lambda x: x[1]))
modifying = False
def outputvalue(name, lines, rewindcomments=False):
if values[name] is None:
return
- rawtext = '%s = "%s"\n' % (name, values[name])
+ rawtext = '%s = "%s"%s' % (name, values[name], newline)
addlines = []
if name in nowrap_vars:
addlines.append(rawtext)
@@ -205,19 +211,19 @@ def patch_recipe_file(fn, values, patch=False, relpath=''):
splitvalue = split_var_value(values[name], assignment=False)
if len(splitvalue) > 1:
linesplit = ' \\\n' + (' ' * (len(name) + 4))
- addlines.append('%s = "%s%s"\n' % (name, linesplit.join(splitvalue), linesplit))
+ addlines.append('%s = "%s%s"%s' % (name, linesplit.join(splitvalue), linesplit, newline))
else:
addlines.append(rawtext)
else:
wrapped = textwrap.wrap(rawtext)
for wrapline in wrapped[:-1]:
- addlines.append('%s \\\n' % wrapline)
- addlines.append('%s\n' % wrapped[-1])
+ addlines.append('%s \\%s' % (wrapline, newline))
+ addlines.append('%s%s' % (wrapped[-1], newline))
if rewindcomments:
# Ensure we insert the lines before any leading comments
# (that we'd want to ensure remain leading the next value)
for i, ln in reversed(list(enumerate(lines))):
- if ln[0] != '#':
+ if not ln.startswith('#'):
lines[i+1:i+1] = addlines
break
else:
@@ -230,7 +236,7 @@ def patch_recipe_file(fn, values, patch=False, relpath=''):
if modifying:
# Insert anything that should come before this variable
pos = get_recipe_pos(varname)
- for k in remainingnames.keys()[:]:
+ for k in list(remainingnames):
if remainingnames[k] > -1 and pos >= remainingnames[k] and not k in existingnames:
outputvalue(k, newlines, rewindcomments=True)
del remainingnames[k]
@@ -247,19 +253,33 @@ def patch_recipe_file(fn, values, patch=False, relpath=''):
# First run - establish which values we want to set are already in the file
varlist = [re.escape(item) for item in values.keys()]
- with open(fn, 'r') as f:
- changed, fromlines = bb.utils.edit_metadata(f, varlist, patch_recipe_varfunc)
+ bb.utils.edit_metadata(fromlines, varlist, patch_recipe_varfunc)
# Second run - actually set everything
modifying = True
varlist.extend(recipe_progression_restrs)
changed, tolines = bb.utils.edit_metadata(fromlines, varlist, patch_recipe_varfunc, match_overrides=True)
if remainingnames:
- if tolines[-1].strip() != '':
+ if tolines and tolines[-1].strip() != '':
tolines.append('\n')
for k in remainingnames.keys():
outputvalue(k, tolines)
+ return changed, tolines
+
+
+def patch_recipe_file(fn, values, patch=False, relpath=''):
+ """Update or insert variable values into a recipe file (assuming you
+ have already identified the exact file you want to update.)
+ Note that some manual inspection/intervention may be required
+ since this cannot handle all situations.
+ """
+
+ with open(fn, 'r') as f:
+ fromlines = f.readlines()
+
+ _, tolines = patch_recipe_lines(fromlines, values)
+
if patch:
relfn = os.path.relpath(fn, relpath)
diff = difflib.unified_diff(fromlines, tolines, 'a/%s' % relfn, 'b/%s' % relfn)
@@ -318,7 +338,7 @@ def patch_recipe(d, fn, varvalues, patch=False, relpath=''):
varfiles = get_var_files(fn, varlist, d)
locs = localise_file_vars(fn, varfiles, varlist)
patches = []
- for f,v in locs.iteritems():
+ for f,v in locs.items():
vals = {k: varvalues[k] for k in v}
patchdata = patch_recipe_file(f, vals, patch, relpath)
if patch:
@@ -347,6 +367,7 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True):
# Copy local files to target directory and gather any remote files
bb_dir = os.path.dirname(d.getVar('FILE', True)) + os.sep
remotes = []
+ copied = []
includes = [path for path in d.getVar('BBINCLUDED', True).split() if
path.startswith(bb_dir) and os.path.exists(path)]
for path in fetch.localpaths() + includes:
@@ -358,13 +379,14 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True):
if not os.path.exists(subdir):
os.makedirs(subdir)
shutil.copy2(path, os.path.join(tgt_dir, relpath))
+ copied.append(relpath)
else:
remotes.append(path)
# Simply copy whole meta dir, if requested
if whole_dir:
shutil.copytree(bb_dir, tgt_dir)
- return remotes
+ return copied, remotes
def get_recipe_local_files(d, patches=False):
@@ -378,8 +400,16 @@ def get_recipe_local_files(d, patches=False):
bb.utils.exec_flat_python_func('patch_path', uri, fetch, '')):
continue
# Skip files that are referenced by absolute path
- if not os.path.isabs(fetch.ud[uri].basepath):
- ret[fetch.ud[uri].basepath] = fetch.localpath(uri)
+ fname = fetch.ud[uri].basepath
+ if os.path.isabs(fname):
+ continue
+ # Handle subdir=
+ subdir = fetch.ud[uri].parm.get('subdir', '')
+ if subdir:
+ if os.path.isabs(subdir):
+ continue
+ fname = os.path.join(subdir, fname)
+ ret[fname] = fetch.localpath(uri)
return ret
@@ -419,8 +449,8 @@ def get_recipe_patched_files(d):
def validate_pn(pn):
"""Perform validation on a recipe name (PN) for a new recipe."""
reserved_names = ['forcevariable', 'append', 'prepend', 'remove']
- if not re.match('[0-9a-z-.]+', pn):
- return 'Recipe name "%s" is invalid: only characters 0-9, a-z, - and . are allowed' % pn
+ if not re.match('^[0-9a-z-.+]+$', pn):
+ return 'Recipe name "%s" is invalid: only characters 0-9, a-z, -, + and . are allowed' % pn
elif pn in reserved_names:
return 'Recipe name "%s" is invalid: is a reserved keyword' % pn
elif pn.startswith('pn-'):
@@ -430,6 +460,60 @@ def validate_pn(pn):
return ''
+def get_bbfile_path(d, destdir, extrapathhint=None):
+ """
+ Determine the correct path for a recipe within a layer
+ Parameters:
+ d: Recipe-specific datastore
+ destdir: destination directory. Can be the path to the base of the layer or a
+ partial path somewhere within the layer.
+ extrapathhint: a path relative to the base of the layer to try
+ """
+ import bb.cookerdata
+
+ destdir = os.path.abspath(destdir)
+ destlayerdir = find_layerdir(destdir)
+
+ # Parse the specified layer's layer.conf file directly, in case the layer isn't in bblayers.conf
+ confdata = d.createCopy()
+ confdata.setVar('BBFILES', '')
+ confdata.setVar('LAYERDIR', destlayerdir)
+ destlayerconf = os.path.join(destlayerdir, "conf", "layer.conf")
+ confdata = bb.cookerdata.parse_config_file(destlayerconf, confdata)
+ pn = d.getVar('PN', True)
+
+ bbfilespecs = (confdata.getVar('BBFILES', True) or '').split()
+ if destdir == destlayerdir:
+ for bbfilespec in bbfilespecs:
+ if not bbfilespec.endswith('.bbappend'):
+ for match in glob.glob(bbfilespec):
+ splitext = os.path.splitext(os.path.basename(match))
+ if splitext[1] == '.bb':
+ mpn = splitext[0].split('_')[0]
+ if mpn == pn:
+ return os.path.dirname(match)
+
+ # Try to make up a path that matches BBFILES
+ # this is a little crude, but better than nothing
+ bpn = d.getVar('BPN', True)
+ recipefn = os.path.basename(d.getVar('FILE', True))
+ pathoptions = [destdir]
+ if extrapathhint:
+ pathoptions.append(os.path.join(destdir, extrapathhint))
+ if destdir == destlayerdir:
+ pathoptions.append(os.path.join(destdir, 'recipes-%s' % bpn, bpn))
+ pathoptions.append(os.path.join(destdir, 'recipes', bpn))
+ pathoptions.append(os.path.join(destdir, bpn))
+ elif not destdir.endswith(('/' + pn, '/' + bpn)):
+ pathoptions.append(os.path.join(destdir, bpn))
+ closepath = ''
+ for pathoption in pathoptions:
+ bbfilepath = os.path.join(pathoption, 'test.bb')
+ for bbfilespec in bbfilespecs:
+ if fnmatch.fnmatchcase(bbfilepath, bbfilespec):
+ return pathoption
+ return None
+
def get_bbappend_path(d, destlayerdir, wildcardver=False):
"""Determine how a bbappend for a recipe should be named and located within another layer"""
@@ -536,7 +620,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
bbappendlines = []
if extralines:
if isinstance(extralines, dict):
- for name, value in extralines.iteritems():
+ for name, value in extralines.items():
bbappendlines.append((name, '=', value))
else:
# Do our best to split it
@@ -550,14 +634,14 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
raise Exception('Invalid extralines value passed')
def popline(varname):
- for i in xrange(0, len(bbappendlines)):
+ for i in range(0, len(bbappendlines)):
if bbappendlines[i][0] == varname:
line = bbappendlines.pop(i)
return line
return None
def appendline(varname, op, value):
- for i in xrange(0, len(bbappendlines)):
+ for i in range(0, len(bbappendlines)):
item = bbappendlines[i]
if item[0] == varname:
bbappendlines[i] = (item[0], item[1], item[2] + ' ' + value)
@@ -576,7 +660,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
copyfiles = {}
if srcfiles:
instfunclines = []
- for newfile, origsrcfile in srcfiles.iteritems():
+ for newfile, origsrcfile in srcfiles.items():
srcfile = origsrcfile
srcurientry = None
if not srcfile:
@@ -644,7 +728,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
if removevar in removevalues:
remove = removevalues[removevar]
- if isinstance(remove, basestring):
+ if isinstance(remove, str):
if remove in splitval:
splitval.remove(remove)
changed = True
@@ -674,7 +758,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
varnames = [item[0] for item in bbappendlines]
if removevalues:
- varnames.extend(removevalues.keys())
+ varnames.extend(list(removevalues.keys()))
with open(appendpath, 'r') as f:
(updated, newlines) = bb.utils.edit_metadata(f, varnames, appendfile_varfunc)
@@ -699,7 +783,7 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
if copyfiles:
if machine:
destsubdir = os.path.join(destsubdir, machine)
- for newfile, srcfile in copyfiles.iteritems():
+ for newfile, srcfile in copyfiles.items():
filedest = os.path.join(appenddir, destsubdir, os.path.basename(srcfile))
if os.path.abspath(newfile) != os.path.abspath(filedest):
bb.note('Copying %s to %s' % (newfile, filedest))
@@ -710,14 +794,16 @@ def bbappend_recipe(rd, destlayerdir, srcfiles, install=None, wildcardver=False,
def find_layerdir(fn):
- """ Figure out relative path to base of layer for a file (e.g. a recipe)"""
- pth = os.path.dirname(fn)
+ """ Figure out the path to the base of the layer containing a file (e.g. a recipe)"""
+ pth = fn
layerdir = ''
while pth:
if os.path.exists(os.path.join(pth, 'conf', 'layer.conf')):
layerdir = pth
break
pth = os.path.dirname(pth)
+ if pth == '/':
+ return None
return layerdir
@@ -725,12 +811,12 @@ def replace_dir_vars(path, d):
"""Replace common directory paths with appropriate variable references (e.g. /etc becomes ${sysconfdir})"""
dirvars = {}
# Sort by length so we get the variables we're interested in first
- for var in sorted(d.keys(), key=len):
+ for var in sorted(list(d.keys()), key=len):
if var.endswith('dir') and var.lower() == var:
value = d.getVar(var, True)
if value.startswith('/') and not '\n' in value and value not in dirvars:
dirvars[value] = var
- for dirpath in sorted(dirvars.keys(), reverse=True):
+ for dirpath in sorted(list(dirvars.keys()), reverse=True):
path = path.replace(dirpath, '${%s}' % dirvars[dirpath])
return path
OpenPOWER on IntegriCloud