diff options
Diffstat (limited to 'meta/classes/package.bbclass')
| -rw-r--r-- | meta/classes/package.bbclass | 3518 |
1 files changed, 2000 insertions, 1518 deletions
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass index 96675dedb6..cc466bd1b2 100644 --- a/meta/classes/package.bbclass +++ b/meta/classes/package.bbclass @@ -2,7 +2,7 @@ # Packaging process # # Executive summary: This class iterates over the functions listed in PACKAGEFUNCS -# Taking D and spliting it up into the packages listed in PACKAGES, placing the +# Taking D and splitting it up into the packages listed in PACKAGES, placing the # resulting output in PKGDEST. # # There are the following default steps but PACKAGEFUNCS can be extended: @@ -25,8 +25,8 @@ # The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with # a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg # -# h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any -# depenedencies found. Also stores the package name so anyone else using this library +# h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any +# depenedencies found. Also stores the package name so anyone else using this library # knows which package to depend on. # # i) package_do_pkgconfig - Keep track of which packages need and provide which .pc files @@ -35,11 +35,14 @@ # # k) package_depchains - Adds automatic dependencies to -dbg and -dev packages # -# l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later +# l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later # packaging steps inherit packagedata -inherit prserv +inherit chrpath + +# Need the package_qa_handle_error() in insane.bbclass +inherit insane PKGD = "${WORKDIR}/package" PKGDEST = "${WORKDIR}/packages-split" @@ -51,164 +54,302 @@ ALL_MULTILIB_PACKAGE_ARCHS = "${@all_multilib_tune_values(d, 'PACKAGE_ARCHS')}" # rpm is used for the per-file dependency identification PACKAGE_DEPENDS += "rpm-native" + +# If your postinstall can execute at rootfs creation time rather than on +# target but depends on a native/cross tool in order to execute, you need to +# list that tool in PACKAGE_WRITE_DEPENDS. Target package dependencies belong +# in the package dependencies as normal, this is just for native/cross support +# tools at rootfs build time. +PACKAGE_WRITE_DEPS ??= "" + def legitimize_package_name(s): - """ - Make sure package names are legitimate strings - """ - import re - - def fixutf(m): - cp = m.group(1) - if cp: - return ('\u%s' % cp).decode('unicode_escape').encode('utf-8') - - # Handle unicode codepoints encoded as <U0123>, as in glibc locale files. - s = re.sub('<U([0-9A-Fa-f]{1,4})>', fixutf, s) - - # Remaining package name validity fixes - 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, aux_files_pattern_verbatim=None, allow_links=False): - """ - Used in .bb files to split up dynamically generated subpackages of a - given package, usually plugins or modules. - """ - - ml = d.getVar("MLPREFIX", True) - if ml: - if not output_pattern.startswith(ml): - output_pattern = ml + output_pattern - - newdeps = [] - for dep in (extra_depends or "").split(): - if dep.startswith(ml): - newdeps.append(dep) - else: - newdeps.append(ml + dep) - if newdeps: - extra_depends = " ".join(newdeps) - - dvar = bb.data.getVar('PKGD', d, True) - - packages = bb.data.getVar('PACKAGES', d, True).split() - - 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: - # This is *really* broken - mainpkg = packages[0] - # At least try and patch it up I guess... - if mainpkg.find('-dbg'): - mainpkg = mainpkg.replace('-dbg', '') - if mainpkg.find('-dev'): - mainpkg = mainpkg.replace('-dev', '') - extra_depends = mainpkg - - 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_links and stat.S_ISLNK(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) - oldfiles = bb.data.getVar('FILES_' + pkg, d, True) - if not oldfiles: - 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) - if aux_files_pattern_verbatim: - if type(aux_files_pattern_verbatim) is list: - for fp in aux_files_pattern_verbatim: - the_files.append(fp % m.group(1)) - else: - the_files.append(aux_files_pattern_verbatim % m.group(1)) - bb.data.setVar('FILES_' + pkg, " ".join(the_files), d) - if extra_depends != '': - the_depends = bb.data.getVar('RDEPENDS_' + pkg, d, True) - 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: - 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) + """ + Make sure package names are legitimate strings + """ + import re + + def fixutf(m): + cp = m.group(1) + if cp: + return ('\\u%s' % cp).encode('latin-1').decode('unicode_escape') + + # Handle unicode codepoints encoded as <U0123>, as in glibc locale files. + s = re.sub('<U([0-9A-Fa-f]{1,4})>', fixutf, s) + + # Remaining package name validity fixes + 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, aux_files_pattern_verbatim=None, allow_links=False, summary=None): + """ + Used in .bb files to split up dynamically generated subpackages of a + given package, usually plugins or modules. + + Arguments: + root -- the path in which to search + file_regex -- regular expression to match searched files. Use + parentheses () to mark the part of this expression + that should be used to derive the module name (to be + substituted where %s is used in other function + arguments as noted below) + output_pattern -- pattern to use for the package names. Must include %s. + description -- description to set for each package. Must include %s. + postinst -- postinstall script to use for all packages (as a + string) + recursive -- True to perform a recursive search - default False + hook -- a hook function to be called for every match. The + function will be called with the following arguments + (in the order listed): + f: full path to the file/directory match + pkg: the package name + file_regex: as above + output_pattern: as above + modulename: the module name derived using file_regex + extra_depends -- extra runtime dependencies (RDEPENDS) to be set for + all packages. The default value of None causes a + dependency on the main package (${PN}) - if you do + not want this, pass '' for this parameter. + aux_files_pattern -- extra item(s) to be added to FILES for each + package. Can be a single string item or a list of + strings for multiple items. Must include %s. + postrm -- postrm script to use for all packages (as a string) + allow_dirs -- True allow directories to be matched - default False + prepend -- if True, prepend created packages to PACKAGES instead + of the default False which appends them + match_path -- match file_regex on the whole relative path to the + root rather than just the file name + aux_files_pattern_verbatim -- extra item(s) to be added to FILES for + each package, using the actual derived module name + rather than converting it to something legal for a + package name. Can be a single string item or a list + of strings for multiple items. Must include %s. + allow_links -- True to allow symlinks to be matched - default False + summary -- Summary to set for each package. Must include %s; + defaults to description if not set. + + """ + + dvar = d.getVar('PKGD') + root = d.expand(root) + output_pattern = d.expand(output_pattern) + extra_depends = d.expand(extra_depends) + + # If the root directory doesn't exist, don't error out later but silently do + # no splitting. + if not os.path.exists(dvar + root): + return [] + + ml = d.getVar("MLPREFIX") + if ml: + if not output_pattern.startswith(ml): + output_pattern = ml + output_pattern + + newdeps = [] + for dep in (extra_depends or "").split(): + if dep.startswith(ml): + newdeps.append(dep) + else: + newdeps.append(ml + dep) + if newdeps: + extra_depends = " ".join(newdeps) + + + packages = d.getVar('PACKAGES').split() + split_packages = set() + + 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 = d.getVar("PN") + + if not summary: + summary = description + + for o in sorted(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_links and stat.S_ISLNK(mode)) or (allow_dirs and stat.S_ISDIR(mode))): + continue + on = legitimize_package_name(m.group(1)) + pkg = output_pattern % on + split_packages.add(pkg) + if not pkg in packages: + if prepend: + packages = [pkg] + packages + else: + packages.append(pkg) + oldfiles = d.getVar('FILES_' + pkg) + newfile = os.path.join(root, o) + # These names will be passed through glob() so if the filename actually + # contains * or ? (rare, but possible) we need to handle that specially + newfile = newfile.replace('*', '[*]') + newfile = newfile.replace('?', '[?]') + if not oldfiles: + the_files = [newfile] + 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) + if aux_files_pattern_verbatim: + if type(aux_files_pattern_verbatim) is list: + for fp in aux_files_pattern_verbatim: + the_files.append(fp % m.group(1)) + else: + the_files.append(aux_files_pattern_verbatim % m.group(1)) + d.setVar('FILES_' + pkg, " ".join(the_files)) + else: + d.setVar('FILES_' + pkg, oldfiles + " " + newfile) + if extra_depends != '': + d.appendVar('RDEPENDS_' + pkg, ' ' + extra_depends) + if not d.getVar('DESCRIPTION_' + pkg): + d.setVar('DESCRIPTION_' + pkg, description % on) + if not d.getVar('SUMMARY_' + pkg): + d.setVar('SUMMARY_' + pkg, summary % on) + if postinst: + d.setVar('pkg_postinst_' + pkg, postinst) + if postrm: + d.setVar('pkg_postrm_' + pkg, postrm) + if callable(hook): + hook(f, pkg, file_regex, output_pattern, m.group(1)) + + d.setVar('PACKAGES', ' '.join(packages)) + return list(split_packages) PACKAGE_DEPENDS += "file-native" python () { - if bb.data.getVar('PACKAGES', d, True) != '': - deps = bb.data.getVarFlag('do_package', 'depends', d) or "" - for dep in (bb.data.getVar('PACKAGE_DEPENDS', d, True) or "").split(): + if d.getVar('PACKAGES') != '': + deps = "" + for dep in (d.getVar('PACKAGE_DEPENDS') or "").split(): deps += " %s:do_populate_sysroot" % dep - bb.data.setVarFlag('do_package', 'depends', deps, d) + d.appendVarFlag('do_package', 'depends', deps) - deps = (bb.data.getVarFlag('do_package', 'deptask', d) or "").split() # shlibs requires any DEPENDS to have already packaged for the *.list files - deps.append("do_package") - bb.data.setVarFlag('do_package', 'deptask', " ".join(deps), d) - else: - d.setVar("PACKAGERDEPTASK", "") + d.appendVarFlag('do_package', 'deptask', " do_packagedata") } -def splitfile(file, debugfile, debugsrcdir, d): - # Function to split a single file, called from split_and_strip_files below - # A working 'file' (one which works on the target architecture) - # is split and the split off portions go to debugfile. +# Get a list of files from file vars by searching files under current working directory +# The list contains symlinks, directories and normal files. +def files_from_filevars(filevars): + import os,glob + cpath = oe.cachedpath.CachedPath() + files = [] + for f in filevars: + if os.path.isabs(f): + f = '.' + f + if not f.startswith("./"): + f = './' + f + globbed = glob.glob(f) + if globbed: + if [ f ] != globbed: + files += globbed + continue + files.append(f) + + symlink_paths = [] + for ind, f in enumerate(files): + # Handle directory symlinks. Truncate path to the lowest level symlink + parent = '' + for dirname in f.split('/')[:-1]: + parent = os.path.join(parent, dirname) + if dirname == '.': + continue + if cpath.islink(parent): + bb.warn("FILES contains file '%s' which resides under a " + "directory symlink. Please fix the recipe and use the " + "real path for the file." % f[1:]) + symlink_paths.append(f) + files[ind] = parent + f = parent + break + + if not cpath.islink(f): + if cpath.isdir(f): + newfiles = [ os.path.join(f,x) for x in os.listdir(f) ] + if newfiles: + files += newfiles + + return files, symlink_paths + +# Called in package_<rpm,ipk,deb>.bbclass to get the correct list of configuration files +def get_conffiles(pkg, d): + pkgdest = d.getVar('PKGDEST') + root = os.path.join(pkgdest, pkg) + cwd = os.getcwd() + os.chdir(root) + + conffiles = d.getVar('CONFFILES_%s' % pkg); + if conffiles == None: + conffiles = d.getVar('CONFFILES') + if conffiles == None: + conffiles = "" + conffiles = conffiles.split() + conf_orig_list = files_from_filevars(conffiles)[0] + + # Remove links and directories from conf_orig_list to get conf_list which only contains normal files + conf_list = [] + for f in conf_orig_list: + if os.path.isdir(f): + continue + if os.path.islink(f): + continue + if not os.path.exists(f): + continue + conf_list.append(f) + + # Remove the leading './' + for i in range(0, len(conf_list)): + conf_list[i] = conf_list[i][1:] + + os.chdir(cwd) + return conf_list + +def checkbuildpath(file, d): + tmpdir = d.getVar('TMPDIR') + with open(file) as f: + file_content = f.read() + if tmpdir in file_content: + return True + + return False + +def splitdebuginfo(file, debugfile, debugsrcdir, sourcefile, d): + # Function to split a single file into two components, one is the stripped + # target system binary, the other contains any debugging information. The + # two files are linked to reference each other. # - # The debug information is then processed for src references. These - # references are copied to debugsrcdir, if defined. + # sourcefile is also generated containing a list of debugsources - import commands, stat + import stat - dvar = bb.data.getVar('PKGD', d, True) - pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True) - objcopy = bb.data.getVar("OBJCOPY", d, True) - debugedit = bb.data.expand("${STAGING_LIBDIR_NATIVE}/rpm/bin/debugedit", d) - workdir = bb.data.expand("${WORKDIR}", d) - workparentdir = os.path.dirname(workdir) - sourcefile = bb.data.expand("${WORKDIR}/debugsources.list", d) + dvar = d.getVar('PKGD') + objcopy = d.getVar("OBJCOPY") + debugedit = d.expand("${STAGING_LIBDIR_NATIVE}/rpm/debugedit") # We ignore kernel modules, we don't generate debug info files. if file.find("/lib/modules/") != -1 and file.endswith(".ko"): - return 1 + return 1 newmode = None if not os.access(file, os.W_OK) or os.access(file, os.R_OK): @@ -218,875 +359,1082 @@ def splitfile(file, debugfile, debugsrcdir, d): # We need to extract the debug src information here... if debugsrcdir: - os.system("%s'%s' -b '%s' -d '%s' -i -l '%s' '%s'" % (pathprefix, debugedit, workparentdir, debugsrcdir, sourcefile, file)) + cmd = "'%s' -i -l '%s' '%s'" % (debugedit, sourcefile, file) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("debugedit failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) - bb.mkdirhier(os.path.dirname(debugfile)) + bb.utils.mkdirhier(os.path.dirname(debugfile)) - os.system("%s'%s' --only-keep-debug '%s' '%s'" % (pathprefix, objcopy, file, debugfile)) + cmd = "'%s' --only-keep-debug '%s' '%s'" % (objcopy, file, debugfile) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("objcopy failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) # Set the debuglink to have the view of the file path on the target - os.system("%s'%s' --add-gnu-debuglink='%s' '%s'" % (pathprefix, objcopy, debugfile, file)) + cmd = "'%s' --add-gnu-debuglink='%s' '%s'" % (objcopy, debugfile, file) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("objcopy failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) if newmode: os.chmod(file, origmode) return 0 -def splitfile2(debugsrcdir, d): - # Function to split a single file, called from split_and_strip_files below - # - # The debug src information processed in the splitfile2 is further procecessed +def copydebugsources(debugsrcdir, d): + # The debug src information written out to sourcefile is further procecessed # and copied to the destination here. - import commands, stat - - dvar = bb.data.getVar('PKGD', d, True) - pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True) - strip = bb.data.getVar("STRIP", d, True) - objcopy = bb.data.getVar("OBJCOPY", d, True) - debugedit = bb.data.expand("${STAGING_LIBDIR_NATIVE}/rpm/bin/debugedit", d) - workdir = bb.data.expand("${WORKDIR}", d) - workparentdir = os.path.dirname(workdir) - workbasedir = os.path.basename(workdir) - sourcefile = bb.data.expand("${WORKDIR}/debugsources.list", d) - - if debugsrcdir: - bb.mkdirhier("%s%s" % (dvar, debugsrcdir)) - - processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '(<internal>|<built-in>)$' | " - # We need to ignore files that are not actually ours - # we do this by only paying attention to items from this package - processdebugsrc += "fgrep -z '%s' | " - processdebugsrc += "(cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s' 2>/dev/null)" - - os.system(processdebugsrc % (sourcefile, workbasedir, workparentdir, dvar, debugsrcdir)) - - # The copy by cpio may have resulted in some empty directories! Remove these - for root, dirs, files in os.walk("%s%s" % (dvar, debugsrcdir)): - for d in dirs: - dir = os.path.join(root, d) - #bb.note("rmdir -p %s" % dir) - os.system("rmdir -p %s 2>/dev/null" % dir) - -def runstrip(file, elftype, d): - # Function to strip a single file, called from split_and_strip_files below - # A working 'file' (one which works on the target architecture) - # - # The elftype is a bit pattern (explained in split_and_strip_files) to tell - # us what type of file we're processing... - # 4 - executable - # 8 - shared library - - import commands, stat - - pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True) - strip = bb.data.getVar("STRIP", d, True) - - # Handle kernel modules specifically - .debug directories here are pointless - if file.find("/lib/modules/") != -1 and file.endswith(".ko"): - return os.system("%s'%s' --strip-debug --remove-section=.comment --remove-section=.note --preserve-dates '%s'" % (pathprefix, strip, file)) - - newmode = None - if not os.access(file, os.W_OK) or os.access(file, os.R_OK): - origmode = os.stat(file)[stat.ST_MODE] - newmode = origmode | stat.S_IWRITE | stat.S_IREAD - os.chmod(file, newmode) - - extraflags = "" - # .so and shared library - if ".so" in file and elftype & 8: - extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded" - # shared or executable: - elif elftype & 8 or elftype & 4: - extraflags = "--remove-section=.comment --remove-section=.note" - - stripcmd = "'%s' %s '%s'" % (strip, extraflags, file) - bb.debug(1, "runstrip: %s" % stripcmd) - - ret = os.system("%s%s" % (pathprefix, stripcmd)) - - if newmode: - os.chmod(file, origmode) - - if ret: - bb.error("runstrip: '%s' strip command failed" % stripcmd) - - return 0 + import stat + + sourcefile = d.expand("${WORKDIR}/debugsources.list") + if debugsrcdir and os.path.isfile(sourcefile): + dvar = d.getVar('PKGD') + strip = d.getVar("STRIP") + objcopy = d.getVar("OBJCOPY") + debugedit = d.expand("${STAGING_LIBDIR_NATIVE}/rpm/bin/debugedit") + workdir = d.getVar("WORKDIR") + workparentdir = os.path.dirname(os.path.dirname(workdir)) + workbasedir = os.path.basename(os.path.dirname(workdir)) + "/" + os.path.basename(workdir) + + # If build path exists in sourcefile, it means toolchain did not use + # -fdebug-prefix-map to compile + if checkbuildpath(sourcefile, d): + localsrc_prefix = workparentdir + "/" + else: + localsrc_prefix = "/usr/src/debug/" + + nosuchdir = [] + basepath = dvar + for p in debugsrcdir.split("/"): + basepath = basepath + "/" + p + if not cpath.exists(basepath): + nosuchdir.append(basepath) + bb.utils.mkdirhier(basepath) + cpath.updatecache(basepath) + + # Ignore files from the recipe sysroots (target and native) + processdebugsrc = "LC_ALL=C ; sort -z -u '%s' | egrep -v -z '((<internal>|<built-in>)$|/.*recipe-sysroot.*/)' | " + # We need to ignore files that are not actually ours + # we do this by only paying attention to items from this package + processdebugsrc += "fgrep -zw '%s' | " + # Remove prefix in the source paths + processdebugsrc += "sed 's#%s##g' | " + processdebugsrc += "(cd '%s' ; cpio -pd0mlL --no-preserve-owner '%s%s' 2>/dev/null)" + + cmd = processdebugsrc % (sourcefile, workbasedir, localsrc_prefix, workparentdir, dvar, debugsrcdir) + (retval, output) = oe.utils.getstatusoutput(cmd) + # Can "fail" if internal headers/transient sources are attempted + #if retval: + # bb.fatal("debug source copy failed with exit code %s (cmd was %s)" % (retval, cmd)) + + # cpio seems to have a bug with -lL together and symbolic links are just copied, not dereferenced. + # Work around this by manually finding and copying any symbolic links that made it through. + cmd = "find %s%s -type l -print0 -delete | sed s#%s%s/##g | (cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s' 2>/dev/null)" % (dvar, debugsrcdir, dvar, debugsrcdir, workparentdir, dvar, debugsrcdir) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("debugsrc symlink fixup failed with exit code %s (cmd was %s)" % (retval, cmd)) + + # The copy by cpio may have resulted in some empty directories! Remove these + cmd = "find %s%s -empty -type d -delete" % (dvar, debugsrcdir) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("empty directory removal failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) + + # Also remove debugsrcdir if its empty + for p in nosuchdir[::-1]: + if os.path.exists(p) and not os.listdir(p): + os.rmdir(p) # # Package data handling routines # -def get_package_mapping (pkg, d): - import oe.packagedata +def get_package_mapping (pkg, basepkg, d): + import oe.packagedata - data = oe.packagedata.read_subpkgdata(pkg, d) - key = "PKG_%s" % pkg + data = oe.packagedata.read_subpkgdata(pkg, d) + key = "PKG_%s" % pkg - if key in data: - return data[key] + if key in data: + # Have to avoid undoing the write_extra_pkgs(global_variants...) + if bb.data.inherits_class('allarch', d) and data[key] == basepkg: + return pkg + return data[key] - return pkg + return pkg -def runtime_mapping_rename (varname, d): - #bb.note("%s before: %s" % (varname, bb.data.getVar(varname, d, True))) +def get_package_additional_metadata (pkg_type, d): + base_key = "PACKAGE_ADD_METADATA" + for key in ("%s_%s" % (base_key, pkg_type.upper()), base_key): + if d.getVar(key, False) is None: + continue + d.setVarFlag(key, "type", "list") + if d.getVarFlag(key, "separator") is None: + d.setVarFlag(key, "separator", "\\n") + metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)] + return "\n".join(metadata_fields).strip() - new_depends = [] - deps = bb.utils.explode_dep_versions(bb.data.getVar(varname, d, True) or "") - for depend in deps: - # Have to be careful with any version component of the depend - new_depend = get_package_mapping(depend, d) - if deps[depend]: - new_depends.append("%s (%s)" % (new_depend, deps[depend])) - else: - new_depends.append(new_depend) +def runtime_mapping_rename (varname, pkg, d): + #bb.note("%s before: %s" % (varname, d.getVar(varname))) - bb.data.setVar(varname, " ".join(new_depends) or None, d) + new_depends = {} + deps = bb.utils.explode_dep_versions2(d.getVar(varname) or "") + for depend in deps: + new_depend = get_package_mapping(depend, pkg, d) + new_depends[new_depend] = deps[depend] - #bb.note("%s after: %s" % (varname, bb.data.getVar(varname, d, True))) + d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False)) + + #bb.note("%s after: %s" % (varname, d.getVar(varname))) # # Package functions suitable for inclusion in PACKAGEFUNCS # python package_get_auto_pr() { - if d.getVar('USE_PR_SERV', True) != "0": - auto_pr=prserv_get_pr_auto(d) - if auto_pr is None: - bb.fatal("Can NOT get auto PR revision from remote PR service") - return - d.setVar('PRAUTO',str(auto_pr)) + import oe.prservice + import re + + # Support per recipe PRSERV_HOST + pn = d.getVar('PN') + host = d.getVar("PRSERV_HOST_" + pn) + if not (host is None): + d.setVar("PRSERV_HOST", host) + + pkgv = d.getVar("PKGV") + + # PR Server not active, handle AUTOINC + if not d.getVar('PRSERV_HOST'): + if 'AUTOINC' in pkgv: + d.setVar("PKGV", pkgv.replace("AUTOINC", "0")) + return + + auto_pr = None + pv = d.getVar("PV") + version = d.getVar("PRAUTOINX") + pkgarch = d.getVar("PACKAGE_ARCH") + checksum = d.getVar("BB_TASKHASH") + + if d.getVar('PRSERV_LOCKDOWN'): + auto_pr = d.getVar('PRAUTO_' + version + '_' + pkgarch) or d.getVar('PRAUTO_' + version) or None + if auto_pr is None: + bb.fatal("Can NOT get PRAUTO from lockdown exported file") + d.setVar('PRAUTO',str(auto_pr)) + return + + try: + conn = d.getVar("__PRSERV_CONN") + if conn is None: + conn = oe.prservice.prserv_make_conn(d) + if conn is not None: + if "AUTOINC" in pkgv: + srcpv = bb.fetch2.get_srcrev(d) + base_ver = "AUTOINC-%s" % version[:version.find(srcpv)] + value = conn.getPR(base_ver, pkgarch, srcpv) + d.setVar("PKGV", pkgv.replace("AUTOINC", str(value))) + + auto_pr = conn.getPR(version, pkgarch, checksum) + except Exception as e: + bb.fatal("Can NOT get PRAUTO, exception %s" % str(e)) + if auto_pr is None: + bb.fatal("Can NOT get PRAUTO from remote PR service") + d.setVar('PRAUTO',str(auto_pr)) } +LOCALEBASEPN ??= "${PN}" + python package_do_split_locales() { - if (bb.data.getVar('PACKAGE_NO_LOCALE', d, True) == '1'): - bb.debug(1, "package requested not splitting locales") - return - - packages = (bb.data.getVar('PACKAGES', d, True) or "").split() - - datadir = bb.data.getVar('datadir', d, True) - if not datadir: - bb.note("datadir not defined") - return - - dvar = bb.data.getVar('PKGD', d, True) - pn = bb.data.getVar('PN', d, True) - - 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) - - # This is *really* broken - mainpkg = packages[0] - # At least try and patch it up I guess... - if mainpkg.find('-dbg'): - mainpkg = mainpkg.replace('-dbg', '') - if mainpkg.find('-dev'): - mainpkg = mainpkg.replace('-dev', '') - - summary = bb.data.getVar('SUMMARY', d, True) or pn - description = bb.data.getVar('DESCRIPTION', d, True) or "" - locale_section = bb.data.getVar('LOCALE_SECTION', d, True) - 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, '%s virtual-locale-%s' % (mainpkg, ln), d) - bb.data.setVar('RPROVIDES_' + pkg, '%s-locale %s-translation' % (pn, ln), d) - bb.data.setVar('SUMMARY_' + pkg, '%s - %s translations' % (summary, l), d) - bb.data.setVar('DESCRIPTION_' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l), d) - if locale_section: - bb.data.setVar('SECTION_' + pkg, locale_section, d) - - bb.data.setVar('PACKAGES', ' '.join(packages), d) - - # Disabled by RP 18/06/07 - # Wildcards aren't supported in debian - # They break with ipkg since glibc-locale* will mean that - # glibc-localedata-translit* won't install as a dependency - # for some other package which breaks meta-toolchain - # Probably breaks since virtual-locale- isn't provided anywhere - #rdep = (bb.data.getVar('RDEPENDS_%s' % mainpkg, d, True) or bb.data.getVar('RDEPENDS', d, True) or "").split() - #rdep.append('%s-locale*' % pn) - #bb.data.setVar('RDEPENDS_%s' % mainpkg, ' '.join(rdep), d) + if (d.getVar('PACKAGE_NO_LOCALE') == '1'): + bb.debug(1, "package requested not splitting locales") + return + + packages = (d.getVar('PACKAGES') or "").split() + + datadir = d.getVar('datadir') + if not datadir: + bb.note("datadir not defined") + return + + dvar = d.getVar('PKGD') + pn = d.getVar('LOCALEBASEPN') + + if pn + '-locale' in packages: + packages.remove(pn + '-locale') + + localedir = os.path.join(dvar + datadir, 'locale') + + if not cpath.isdir(localedir): + bb.debug(1, "No locale files in this package") + return + + locales = os.listdir(localedir) + + summary = d.getVar('SUMMARY') or pn + description = d.getVar('DESCRIPTION') or "" + locale_section = d.getVar('LOCALE_SECTION') + mlprefix = d.getVar('MLPREFIX') or "" + for l in sorted(locales): + ln = legitimize_package_name(l) + pkg = pn + '-locale-' + ln + packages.append(pkg) + d.setVar('FILES_' + pkg, os.path.join(datadir, 'locale', l)) + d.setVar('RRECOMMENDS_' + pkg, '%svirtual-locale-%s' % (mlprefix, ln)) + d.setVar('RPROVIDES_' + pkg, '%s-locale %s%s-translation' % (pn, mlprefix, ln)) + d.setVar('SUMMARY_' + pkg, '%s - %s translations' % (summary, l)) + d.setVar('DESCRIPTION_' + pkg, '%s This package contains language translation files for the %s locale.' % (description, l)) + if locale_section: + d.setVar('SECTION_' + pkg, locale_section) + + d.setVar('PACKAGES', ' '.join(packages)) + + # Disabled by RP 18/06/07 + # Wildcards aren't supported in debian + # They break with ipkg since glibc-locale* will mean that + # glibc-localedata-translit* won't install as a dependency + # for some other package which breaks meta-toolchain + # Probably breaks since virtual-locale- isn't provided anywhere + #rdep = (d.getVar('RDEPENDS_%s' % pn) or "").split() + #rdep.append('%s-locale*' % pn) + #d.setVar('RDEPENDS_%s' % pn, ' '.join(rdep)) } python perform_packagecopy () { - dest = bb.data.getVar('D', d, True) - dvar = bb.data.getVar('PKGD', d, True) - - bb.mkdirhier(dvar) - - # Start by package population by taking a copy of the installed - # files to operate on - os.system('rm -rf %s/*' % (dvar)) - # Preserve sparse files and hard links - os.system('tar -cf - -C %s -ps . | tar -xf - -C %s' % (dest, dvar)) + dest = d.getVar('D') + dvar = d.getVar('PKGD') + + # Start by package population by taking a copy of the installed + # files to operate on + # Preserve sparse files and hard links + cmd = 'tar -cf - -C %s -p . | tar -xf - -C %s' % (dest, dvar) + (retval, output) = oe.utils.getstatusoutput(cmd) + if retval: + bb.fatal("file copy failed with exit code %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) + + # replace RPATHs for the nativesdk binaries, to make them relocatable + if bb.data.inherits_class('nativesdk', d) or bb.data.inherits_class('cross-canadian', d): + rpath_replace (dvar, d) } +perform_packagecopy[cleandirs] = "${PKGD}" +perform_packagecopy[dirs] = "${PKGD}" # We generate a master list of directories to process, we start by # seeding this list with reasonable defaults, then load from # the fs-perms.txt files python fixup_perms () { - import os, pwd, grp - - # init using a string with the same format as a line as documented in - # the fs-perms.txt file - # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid> - # <path> link <link target> - # - # __str__ can be used to print out an entry in the input format - # - # if fs_perms_entry.path is None: - # an error occured - # if fs_perms_entry.link, you can retrieve: - # fs_perms_entry.path = path - # fs_perms_entry.link = target of link - # if not fs_perms_entry.link, you can retrieve: - # fs_perms_entry.path = path - # fs_perms_entry.mode = expected dir mode or None - # fs_perms_entry.uid = expected uid or -1 - # fs_perms_entry.gid = expected gid or -1 - # fs_perms_entry.walk = 'true' or something else - # fs_perms_entry.fmode = expected file mode or None - # fs_perms_entry.fuid = expected file uid or -1 - # fs_perms_entry_fgid = expected file gid or -1 - class fs_perms_entry(): - def __init__(self, line): - lsplit = line.split() - if len(lsplit) == 3 and lsplit[1].lower() == "link": - self._setlink(lsplit[0], lsplit[2]) - elif len(lsplit) == 8: - self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7]) - else: |
