| # |
| # Copyright OpenEmbedded Contributors |
| # |
| # SPDX-License-Identifier: MIT |
| # |
| |
| WORKDIR_PKGDATA = "${WORKDIR}/pkgdata-sysroot" |
| |
| def package_populate_pkgdata_dir(pkgdatadir, d): |
| import glob |
| |
| postinsts = [] |
| seendirs = set() |
| stagingdir = d.getVar("PKGDATA_DIR") |
| pkgarchs = ['${MACHINE_ARCH}'] |
| pkgarchs = pkgarchs + list(reversed(d.getVar("PACKAGE_EXTRA_ARCHS").split())) |
| pkgarchs.append('allarch') |
| |
| bb.utils.mkdirhier(pkgdatadir) |
| for pkgarch in pkgarchs: |
| for manifest in glob.glob(d.expand("${SSTATE_MANIFESTS}/manifest-%s-*.packagedata" % pkgarch)): |
| with open(manifest, "r") as f: |
| for l in f: |
| l = l.strip() |
| dest = l.replace(stagingdir, "") |
| if l.endswith("/"): |
| staging_copydir(l, pkgdatadir, dest, seendirs) |
| continue |
| try: |
| staging_copyfile(l, pkgdatadir, dest, postinsts, seendirs) |
| except FileExistsError: |
| continue |
| |
| python package_prepare_pkgdata() { |
| import copy |
| import glob |
| |
| taskdepdata = d.getVar("BB_TASKDEPDATA", False) |
| mytaskname = d.getVar("BB_RUNTASK") |
| if mytaskname.endswith("_setscene"): |
| mytaskname = mytaskname.replace("_setscene", "") |
| workdir = d.getVar("WORKDIR") |
| pn = d.getVar("PN") |
| stagingdir = d.getVar("PKGDATA_DIR") |
| pkgdatadir = d.getVar("WORKDIR_PKGDATA") |
| |
| # Detect bitbake -b usage |
| nodeps = d.getVar("BB_LIMITEDDEPS") or False |
| if nodeps: |
| staging_package_populate_pkgdata_dir(pkgdatadir, d) |
| return |
| |
| start = None |
| configuredeps = [] |
| for dep in taskdepdata: |
| data = taskdepdata[dep] |
| if data[1] == mytaskname and data[0] == pn: |
| start = dep |
| break |
| if start is None: |
| bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?") |
| |
| # We need to figure out which sysroot files we need to expose to this task. |
| # This needs to match what would get restored from sstate, which is controlled |
| # ultimately by calls from bitbake to setscene_depvalid(). |
| # That function expects a setscene dependency tree. We build a dependency tree |
| # condensed to inter-sstate task dependencies, similar to that used by setscene |
| # tasks. We can then call into setscene_depvalid() and decide |
| # which dependencies we can "see" and should expose in the recipe specific sysroot. |
| setscenedeps = copy.deepcopy(taskdepdata) |
| |
| start = set([start]) |
| |
| sstatetasks = d.getVar("SSTATETASKS").split() |
| # Add recipe specific tasks referenced by setscene_depvalid() |
| sstatetasks.append("do_stash_locale") |
| |
| # If start is an sstate task (like do_package) we need to add in its direct dependencies |
| # else the code below won't recurse into them. |
| for dep in set(start): |
| for dep2 in setscenedeps[dep][3]: |
| start.add(dep2) |
| start.remove(dep) |
| |
| # Create collapsed do_populate_sysroot -> do_populate_sysroot tree |
| for dep in taskdepdata: |
| data = setscenedeps[dep] |
| if data[1] not in sstatetasks: |
| for dep2 in setscenedeps: |
| data2 = setscenedeps[dep2] |
| if dep in data2[3]: |
| data2[3].update(setscenedeps[dep][3]) |
| data2[3].remove(dep) |
| if dep in start: |
| start.update(setscenedeps[dep][3]) |
| start.remove(dep) |
| del setscenedeps[dep] |
| |
| # Remove circular references |
| for dep in setscenedeps: |
| if dep in setscenedeps[dep][3]: |
| setscenedeps[dep][3].remove(dep) |
| |
| # Direct dependencies should be present and can be depended upon |
| for dep in set(start): |
| if setscenedeps[dep][1] == "do_packagedata": |
| if dep not in configuredeps: |
| configuredeps.append(dep) |
| |
| msgbuf = [] |
| # Call into setscene_depvalid for each sub-dependency and only copy sysroot files |
| # for ones that would be restored from sstate. |
| done = list(start) |
| next = list(start) |
| while next: |
| new = [] |
| for dep in next: |
| data = setscenedeps[dep] |
| for datadep in data[3]: |
| if datadep in done: |
| continue |
| taskdeps = {} |
| taskdeps[dep] = setscenedeps[dep][:2] |
| taskdeps[datadep] = setscenedeps[datadep][:2] |
| retval = setscene_depvalid(datadep, taskdeps, [], d, msgbuf) |
| done.append(datadep) |
| new.append(datadep) |
| if retval: |
| msgbuf.append("Skipping setscene dependency %s" % datadep) |
| continue |
| if datadep not in configuredeps and setscenedeps[datadep][1] == "do_packagedata": |
| configuredeps.append(datadep) |
| msgbuf.append("Adding dependency on %s" % setscenedeps[datadep][0]) |
| else: |
| msgbuf.append("Following dependency on %s" % setscenedeps[datadep][0]) |
| next = new |
| |
| # This logging is too verbose for day to day use sadly |
| #bb.debug(2, "\n".join(msgbuf)) |
| |
| seendirs = set() |
| postinsts = [] |
| multilibs = {} |
| manifests = {} |
| |
| msg_adding = [] |
| |
| for dep in configuredeps: |
| c = setscenedeps[dep][0] |
| msg_adding.append(c) |
| |
| manifest, d2 = oe.sstatesig.find_sstate_manifest(c, setscenedeps[dep][2], "packagedata", d, multilibs) |
| destsysroot = pkgdatadir |
| |
| if manifest: |
| targetdir = destsysroot |
| with open(manifest, "r") as f: |
| manifests[dep] = manifest |
| for l in f: |
| l = l.strip() |
| dest = targetdir + l.replace(stagingdir, "") |
| if l.endswith("/"): |
| staging_copydir(l, targetdir, dest, seendirs) |
| continue |
| staging_copyfile(l, targetdir, dest, postinsts, seendirs) |
| |
| bb.note("Installed into pkgdata-sysroot: %s" % str(msg_adding)) |
| |
| } |
| package_prepare_pkgdata[cleandirs] = "${WORKDIR_PKGDATA}" |
| package_prepare_pkgdata[vardepsexclude] += "MACHINE_ARCH PACKAGE_EXTRA_ARCHS SDK_ARCH BUILD_ARCH SDK_OS BB_TASKDEPDATA SSTATETASKS" |
| |
| |