def include(oldfn, fn, data, error_out):
    """
    error_out If True a ParseError will be raised if the to be included
    config-files could not be included.
    """
    if oldfn == fn: # prevent infinite recursion
        return None

    import bb
    fn = bb.data.expand(fn, data)
    oldfn = bb.data.expand(oldfn, data)

    if not os.path.isabs(fn):
        dname = os.path.dirname(oldfn)
        bbpath = "%s:%s" % (dname, bb.data.getVar("BBPATH", data, 1))
        abs_fn = bb.utils.which(bbpath, fn)
        if abs_fn:
            fn = abs_fn

    from bb.parse import handle
    try:
        ret = handle(fn, data, True)
    except IOError:
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars() )
        logger.debug(2, "CONF file '%s' not found", fn)
Exemplo n.º 2
0
def include(parentfn, fn, lineno, data, error_out):
    """
    error_out: A string indicating the verb (e.g. "include", "inherit") to be
    used in a ParseError that will be raised if the file to be included could
    not be included. Specify False to avoid raising an error in this case.
    """
    if parentfn == fn:  # prevent infinite recursion
        return None

    fn = data.expand(fn)
    parentfn = data.expand(parentfn)

    if not os.path.isabs(fn):
        dname = os.path.dirname(parentfn)
        bbpath = "%s:%s" % (dname, data.getVar("BBPATH", True))
        abs_fn, attempts = bb.utils.which(bbpath, fn, history=True)
        if abs_fn and bb.parse.check_dependency(data, abs_fn):
            logger.warn("Duplicate inclusion for %s in %s" % (abs_fn, data.getVar("FILE", True)))
        for af in attempts:
            bb.parse.mark_dependency(data, af)
        if abs_fn:
            fn = abs_fn
    elif bb.parse.check_dependency(data, fn):
        logger.warn("Duplicate inclusion for %s in %s" % (fn, data.getVar("FILE", True)))

    try:
        ret = bb.parse.handle(fn, data, True)
    except (IOError, OSError):
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), parentfn, lineno)
        logger.debug(2, "CONF file '%s' not found", fn)
Exemplo n.º 3
0
def include(oldfn, fn, lineno, data, error_out):
    """
    error_out: A string indicating the verb (e.g. "include", "inherit") to be
    used in a ParseError that will be raised if the file to be included could
    not be included. Specify False to avoid raising an error in this case.
    """
    if oldfn == fn:  # prevent infinite recursion
        return None

    import bb
    fn = data.expand(fn)
    oldfn = data.expand(oldfn)

    if not os.path.isabs(fn):
        dname = os.path.dirname(oldfn)
        bbpath = "%s:%s" % (dname, data.getVar("BBPATH", True))
        abs_fn = bb.utils.which(bbpath, fn)
        if abs_fn:
            fn = abs_fn

    from bb.parse import handle
    try:
        ret = handle(fn, data, True)
    except IOError:
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars(),
                             oldfn, lineno)
        logger.debug(2, "CONF file '%s' not found", fn)
Exemplo n.º 4
0
def include(oldfn, fn, lineno, data, error_out):
    """
    error_out: A string indicating the verb (e.g. "include", "inherit") to be
    used in a ParseError that will be raised if the file to be included could
    not be included. Specify False to avoid raising an error in this case.
    """
    if oldfn == fn:  # prevent infinite recursion
        return None

    import bb

    fn = data.expand(fn)
    oldfn = data.expand(oldfn)

    if not os.path.isabs(fn):
        dname = os.path.dirname(oldfn)
        bbpath = "%s:%s" % (dname, data.getVar("BBPATH", 1))
        abs_fn = bb.utils.which(bbpath, fn)
        if abs_fn:
            fn = abs_fn

    from bb.parse import handle

    try:
        ret = handle(fn, data, True)
    except IOError:
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars(), oldfn, lineno)
        logger.debug(2, "CONF file '%s' not found", fn)
Exemplo n.º 5
0
def include(oldfn, fn, data, error_out):
    """
    error_out If True a ParseError will be raised if the to be included
    config-files could not be included.
    """
    if oldfn == fn:  # prevent infinite recursion
        return None

    import bb
    fn = bb.data.expand(fn, data)
    oldfn = bb.data.expand(oldfn, data)

    if not os.path.isabs(fn):
        dname = os.path.dirname(oldfn)
        bbpath = "%s:%s" % (dname, bb.data.getVar("BBPATH", data, 1))
        abs_fn = bb.utils.which(bbpath, fn)
        if abs_fn:
            fn = abs_fn

    from bb.parse import handle
    try:
        ret = handle(fn, data, True)
    except IOError:
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars())
        logger.debug(2, "CONF file '%s' not found", fn)
Exemplo n.º 6
0
def include_single_file(parentfn, fn, lineno, data, error_out):
    """
    Helper function for include() which does not expand or split its parameters.
    """
    if parentfn == fn: # prevent infinite recursion
        return None

    if not os.path.isabs(fn):
        dname = os.path.dirname(parentfn)
        bbpath = "%s:%s" % (dname, data.getVar("BBPATH"))
        abs_fn, attempts = bb.utils.which(bbpath, fn, history=True)
        if abs_fn and bb.parse.check_dependency(data, abs_fn):
            logger.warning("Duplicate inclusion for %s in %s" % (abs_fn, data.getVar('FILE')))
        for af in attempts:
            bb.parse.mark_dependency(data, af)
        if abs_fn:
            fn = abs_fn
    elif bb.parse.check_dependency(data, fn):
        logger.warning("Duplicate inclusion for %s in %s" % (fn, data.getVar('FILE')))

    try:
        bb.parse.handle(fn, data, True)
    except (IOError, OSError) as exc:
        if exc.errno == errno.ENOENT:
            if error_out:
                raise ParseError("Could not %s file %s" % (error_out, fn), parentfn, lineno)
            logger.debug(2, "CONF file '%s' not found", fn)
        else:
            if error_out:
                raise ParseError("Could not %s file %s: %s" % (error_out, fn, exc.strerror), parentfn, lineno)
            else:
                raise ParseError("Error parsing %s: %s" % (fn, exc.strerror), parentfn, lineno)
Exemplo n.º 7
0
def include(parentfn, fn, lineno, data, error_out):
    """
    error_out: A string indicating the verb (e.g. "include", "inherit") to be
    used in a ParseError that will be raised if the file to be included could
    not be included. Specify False to avoid raising an error in this case.
    """
    if parentfn == fn:  # prevent infinite recursion
        return None

    fn = data.expand(fn)
    parentfn = data.expand(parentfn)

    if not os.path.isabs(fn):
        dname = os.path.dirname(parentfn)
        bbpath = "%s:%s" % (dname, data.getVar("BBPATH", True))
        abs_fn, attempts = bb.utils.which(bbpath, fn, history=True)
        if abs_fn and bb.parse.check_dependency(data, abs_fn):
            logger.warn("Duplicate inclusion for %s in %s" %
                        (abs_fn, data.getVar('FILE', True)))
        for af in attempts:
            bb.parse.mark_dependency(data, af)
        if abs_fn:
            fn = abs_fn
    elif bb.parse.check_dependency(data, fn):
        logger.warn("Duplicate inclusion for %s in %s" %
                    (fn, data.getVar('FILE', True)))

    try:
        ret = bb.parse.handle(fn, data, True)
    except (IOError, OSError):
        if error_out:
            raise ParseError("Could not %(error_out)s file %(fn)s" % vars(),
                             parentfn, lineno)
        logger.debug(2, "CONF file '%s' not found", fn)
        bb.parse.mark_dependency(data, fn)
Exemplo n.º 8
0
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND") or "").split()
    for append in appends:
        logger.debug(1, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    onlyfinalise = d.getVar("__ONLYFINALISE", False)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        finalize(fn, d)
    except bb.parse.SkipRecipe as e:
        d.setVar("__SKIPPED", e.args[0])
    datastores = {"": safe_d}

    extended = d.getVar("BBCLASSEXTEND") or ""
    if extended:
        # the following is to support bbextends with arguments, for e.g. multilib
        # an example is as follows:
        #   BBCLASSEXTEND = "multilib:lib32"
        # it will create foo-lib32, inheriting multilib.bbclass and set
        # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32"
        extendedmap = {}
        variantmap = {}

        for ext in extended.split():
            eext = ext.split(':', 2)
            if len(eext) > 1:
                extendedmap[ext] = eext[0]
                variantmap[ext] = eext[1]
            else:
                extendedmap[ext] = ext

        pn = d.getVar("PN")

        def extendfunc(name, d):
            if name != extendedmap[name]:
                d.setVar("BBEXTENDCURR", extendedmap[name])
                d.setVar("BBEXTENDVARIANT", variantmap[name])
            else:
                d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extendedmap.keys(), extendfunc,
                         onlyfinalise)

    for variant in datastores.keys():
        if variant:
            try:
                if not onlyfinalise or variant in onlyfinalise:
                    finalize(fn, datastores[variant], variant)
            except bb.parse.SkipRecipe as e:
                datastores[variant].setVar("__SKIPPED", e.args[0])

    datastores[""] = d
    return datastores
Exemplo n.º 9
0
Arquivo: ast.py Projeto: kraj/bitbake
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND") or "").split()
    for append in appends:
        logger.debug(1, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    onlyfinalise = d.getVar("__ONLYFINALISE", False)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        finalize(fn, d)
    except bb.parse.SkipRecipe as e:
        d.setVar("__SKIPPED", e.args[0])
    datastores = {"": safe_d}

    extended = d.getVar("BBCLASSEXTEND") or ""
    if extended:
        # the following is to support bbextends with arguments, for e.g. multilib
        # an example is as follows:
        #   BBCLASSEXTEND = "multilib:lib32"
        # it will create foo-lib32, inheriting multilib.bbclass and set
        # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32"
        extendedmap = {}
        variantmap = {}

        for ext in extended.split():
            eext = ext.split(":", 2)
            if len(eext) > 1:
                extendedmap[ext] = eext[0]
                variantmap[ext] = eext[1]
            else:
                extendedmap[ext] = ext

        pn = d.getVar("PN")

        def extendfunc(name, d):
            if name != extendedmap[name]:
                d.setVar("BBEXTENDCURR", extendedmap[name])
                d.setVar("BBEXTENDVARIANT", variantmap[name])
            else:
                d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extendedmap.keys(), extendfunc, onlyfinalise)

    for variant in datastores.keys():
        if variant:
            try:
                if not onlyfinalise or variant in onlyfinalise:
                    finalize(fn, datastores[variant], variant)
            except bb.parse.SkipRecipe as e:
                datastores[variant].setVar("__SKIPPED", e.args[0])

    datastores[""] = d
    return datastores
Exemplo n.º 10
0
    def eval(self, data):
        """
        Include the file and evaluate the statements
        """
        s = data.expand(self.what_file)
        logger.debug(2, "CONF %s:%s: including %s", self.filename, self.lineno, s)

        # TODO: Cache those includes... maybe not here though
        if self.force:
            bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, "include required")
        else:
            bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, False)
Exemplo n.º 11
0
    def eval(self, data):
        """
        Include the file and evaluate the statements
        """
        s = data.expand(self.what_file)
        logger.debug(2, "CONF %s:%s: including %s", self.filename, self.lineno, s)

        # TODO: Cache those includes... maybe not here though
        if self.force:
            bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, "include required")
        else:
            bb.parse.ConfHandler.include(self.filename, s, self.lineno, data, False)
Exemplo n.º 12
0
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND", True) or "").split()
    for append in appends:
        logger.debug(2, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    onlyfinalise = d.getVar("__ONLYFINALISE", False)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        finalize(fn, d)
    except bb.parse.SkipPackage as e:
        d.setVar("__SKIPPED", e.args[0])
    datastores = {"": safe_d}

    versions = (d.getVar("BBVERSIONS", True) or "").split()
    if versions:
        pv = orig_pv = d.getVar("PV", True)
        baseversions = {}

        def verfunc(ver, d, pv_d=None):
            if pv_d is None:
                pv_d = d

            overrides = d.getVar("OVERRIDES", True).split(":")
            pv_d.setVar("PV", ver)
            overrides.append(ver)
            bpv = baseversions.get(ver) or orig_pv
            pv_d.setVar("BPV", bpv)
            overrides.append(bpv)
            d.setVar("OVERRIDES", ":".join(overrides))

        versions = list(_expand_versions(versions))
        for pos, version in enumerate(list(versions)):
            try:
                pv, bpv = version.split(":", 2)
            except ValueError:
                pass
            else:
                versions[pos] = pv
                baseversions[pv] = bpv

        if pv in versions and not baseversions.get(pv):
            versions.remove(pv)
        else:
            pv = versions.pop()

            # This is necessary because our existing main datastore
            # has already been finalized with the old PV, we need one
            # that's been finalized with the new PV.
            d = bb.data.createCopy(safe_d)
            verfunc(pv, d, safe_d)
            try:
                finalize(fn, d)
            except bb.parse.SkipPackage as e:
                d.setVar("__SKIPPED", e.args[0])

        _create_variants(datastores, versions, verfunc, onlyfinalise)

    extended = d.getVar("BBCLASSEXTEND", True) or ""
    if extended:
        # the following is to support bbextends with arguments, for e.g. multilib
        # an example is as follows:
        #   BBCLASSEXTEND = "multilib:lib32"
        # it will create foo-lib32, inheriting multilib.bbclass and set
        # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32"
        extendedmap = {}
        variantmap = {}

        for ext in extended.split():
            eext = ext.split(':', 2)
            if len(eext) > 1:
                extendedmap[ext] = eext[0]
                variantmap[ext] = eext[1]
            else:
                extendedmap[ext] = ext

        pn = d.getVar("PN", True)

        def extendfunc(name, d):
            if name != extendedmap[name]:
                d.setVar("BBEXTENDCURR", extendedmap[name])
                d.setVar("BBEXTENDVARIANT", variantmap[name])
            else:
                d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extendedmap.keys(), extendfunc,
                         onlyfinalise)

    for variant, variant_d in datastores.iteritems():
        if variant:
            try:
                if not onlyfinalise or variant in onlyfinalise:
                    finalize(fn, variant_d, variant)
            except bb.parse.SkipPackage as e:
                variant_d.setVar("__SKIPPED", e.args[0])

    if len(datastores) > 1:
        variants = filter(None, datastores.iterkeys())
        safe_d.setVar("__VARIANTS", " ".join(variants))

    datastores[""] = d
    return datastores
Exemplo n.º 13
0
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND", True) or "").split()
    for append in appends:
        logger.debug(2, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    onlyfinalise = d.getVar("__ONLYFINALISE", False)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        finalize(fn, d)
    except bb.parse.SkipPackage as e:
        d.setVar("__SKIPPED", e.args[0])
    datastores = {"": safe_d}

    versions = (d.getVar("BBVERSIONS", True) or "").split()
    if versions:
        pv = orig_pv = d.getVar("PV", True)
        baseversions = {}

        def verfunc(ver, d, pv_d = None):
            if pv_d is None:
                pv_d = d

            overrides = d.getVar("OVERRIDES", True).split(":")
            pv_d.setVar("PV", ver)
            overrides.append(ver)
            bpv = baseversions.get(ver) or orig_pv
            pv_d.setVar("BPV", bpv)
            overrides.append(bpv)
            d.setVar("OVERRIDES", ":".join(overrides))

        versions = list(_expand_versions(versions))
        for pos, version in enumerate(list(versions)):
            try:
                pv, bpv = version.split(":", 2)
            except ValueError:
                pass
            else:
                versions[pos] = pv
                baseversions[pv] = bpv

        if pv in versions and not baseversions.get(pv):
            versions.remove(pv)
        else:
            pv = versions.pop()

            # This is necessary because our existing main datastore
            # has already been finalized with the old PV, we need one
            # that's been finalized with the new PV.
            d = bb.data.createCopy(safe_d)
            verfunc(pv, d, safe_d)
            try:
                finalize(fn, d)
            except bb.parse.SkipPackage as e:
                d.setVar("__SKIPPED", e.args[0])

        _create_variants(datastores, versions, verfunc)

    extended = d.getVar("BBCLASSEXTEND", True) or ""
    if extended:
        # the following is to support bbextends with arguments, for e.g. multilib
        # an example is as follows:
        #   BBCLASSEXTEND = "multilib:lib32"
        # it will create foo-lib32, inheriting multilib.bbclass and set
        # BBEXTENDCURR to "multilib" and BBEXTENDVARIANT to "lib32"
        extendedmap = {}
        variantmap = {}

        for ext in extended.split():
            eext = ext.split(':', 2)
            if len(eext) > 1:
                extendedmap[ext] = eext[0]
                variantmap[ext] = eext[1]
            else:
                extendedmap[ext] = ext

        pn = d.getVar("PN", True)
        def extendfunc(name, d):
            if name != extendedmap[name]:
                d.setVar("BBEXTENDCURR", extendedmap[name])
                d.setVar("BBEXTENDVARIANT", variantmap[name])
            else:
                d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit(extendedmap[name], fn, 0, d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extendedmap.keys(), extendfunc)

    for variant, variant_d in datastores.iteritems():
        if variant:
            try:
                if not onlyfinalise or variant in onlyfinalise:
                    finalize(fn, variant_d, variant)
            except bb.parse.SkipPackage as e:
                variant_d.setVar("__SKIPPED", e.args[0])

    if len(datastores) > 1:
        variants = filter(None, datastores.iterkeys())
        safe_d.setVar("__VARIANTS", " ".join(variants))

    datastores[""] = d
    return datastores
Exemplo n.º 14
0
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND", True) or "").split()
    for append in appends:
        logger.debug(2, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    onlyfinalise = d.getVar("__ONLYFINALISE", False)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        if not onlyfinalise or "default" in onlyfinalise:
            finalize(fn, d)
    except bb.parse.SkipPackage:
        bb.data.setVar("__SKIPPED", True, d)
    datastores = {"": safe_d}

    versions = (d.getVar("BBVERSIONS", True) or "").split()
    if versions:
        pv = orig_pv = d.getVar("PV", True)
        baseversions = {}

        def verfunc(ver, d, pv_d = None):
            if pv_d is None:
                pv_d = d

            overrides = d.getVar("OVERRIDES", True).split(":")
            pv_d.setVar("PV", ver)
            overrides.append(ver)
            bpv = baseversions.get(ver) or orig_pv
            pv_d.setVar("BPV", bpv)
            overrides.append(bpv)
            d.setVar("OVERRIDES", ":".join(overrides))

        versions = list(_expand_versions(versions))
        for pos, version in enumerate(list(versions)):
            try:
                pv, bpv = version.split(":", 2)
            except ValueError:
                pass
            else:
                versions[pos] = pv
                baseversions[pv] = bpv

        if pv in versions and not baseversions.get(pv):
            versions.remove(pv)
        else:
            pv = versions.pop()

            # This is necessary because our existing main datastore
            # has already been finalized with the old PV, we need one
            # that's been finalized with the new PV.
            d = bb.data.createCopy(safe_d)
            verfunc(pv, d, safe_d)
            try:
                finalize(fn, d)
            except bb.parse.SkipPackage:
                bb.data.setVar("__SKIPPED", True, d)

        _create_variants(datastores, versions, verfunc)

    extended = d.getVar("BBCLASSEXTEND", True) or ""
    if extended:
        pn = d.getVar("PN", True)
        def extendfunc(name, d):
            d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit([name], d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extended.split(), extendfunc)

    for variant, variant_d in datastores.iteritems():
        if variant:
            try:
                if not onlyfinalise or variant in onlyfinalise:
                    finalize(fn, variant_d, variant)
            except bb.parse.SkipPackage:
                bb.data.setVar("__SKIPPED", True, variant_d)

    if len(datastores) > 1:
        variants = filter(None, datastores.iterkeys())
        safe_d.setVar("__VARIANTS", " ".join(variants))

    datastores[""] = d
    return datastores
Exemplo n.º 15
0
def multi_finalize(fn, d):
    appends = (d.getVar("__BBAPPEND", True) or "").split()
    for append in appends:
        logger.debug(2, "Appending .bbappend file %s to %s", append, fn)
        bb.parse.BBHandler.handle(append, d, True)

    safe_d = d
    d = bb.data.createCopy(safe_d)
    try:
        finalize(fn, d)
    except bb.parse.SkipPackage:
        bb.data.setVar("__SKIPPED", True, d)
    datastores = {"": safe_d}

    versions = (d.getVar("BBVERSIONS", True) or "").split()
    if versions:
        pv = orig_pv = d.getVar("PV", True)
        baseversions = {}

        def verfunc(ver, d, pv_d=None):
            if pv_d is None:
                pv_d = d

            overrides = d.getVar("OVERRIDES", True).split(":")
            pv_d.setVar("PV", ver)
            overrides.append(ver)
            bpv = baseversions.get(ver) or orig_pv
            pv_d.setVar("BPV", bpv)
            overrides.append(bpv)
            d.setVar("OVERRIDES", ":".join(overrides))

        versions = list(_expand_versions(versions))
        for pos, version in enumerate(list(versions)):
            try:
                pv, bpv = version.split(":", 2)
            except ValueError:
                pass
            else:
                versions[pos] = pv
                baseversions[pv] = bpv

        if pv in versions and not baseversions.get(pv):
            versions.remove(pv)
        else:
            pv = versions.pop()

            # This is necessary because our existing main datastore
            # has already been finalized with the old PV, we need one
            # that's been finalized with the new PV.
            d = bb.data.createCopy(safe_d)
            verfunc(pv, d, safe_d)
            try:
                finalize(fn, d)
            except bb.parse.SkipPackage:
                bb.data.setVar("__SKIPPED", True, d)

        _create_variants(datastores, versions, verfunc)

    extended = d.getVar("BBCLASSEXTEND", True) or ""
    if extended:
        pn = d.getVar("PN", True)

        def extendfunc(name, d):
            d.setVar("PN", "%s-%s" % (pn, name))
            bb.parse.BBHandler.inherit([name], d)

        safe_d.setVar("BBCLASSEXTEND", extended)
        _create_variants(datastores, extended.split(), extendfunc)

    for variant, variant_d in datastores.iteritems():
        if variant:
            try:
                finalize(fn, variant_d, variant)
            except bb.parse.SkipPackage:
                bb.data.setVar("__SKIPPED", True, variant_d)

    if len(datastores) > 1:
        variants = filter(None, datastores.iterkeys())
        safe_d.setVar("__VARIANTS", " ".join(variants))

    datastores[""] = d
    return datastores