xref: /openbmc/openbmc/poky/bitbake/lib/bb/__init__.py (revision 2f814a6d)
1eb8dc403SDave Cobbley#
2eb8dc403SDave Cobbley# BitBake Build System Python Library
3eb8dc403SDave Cobbley#
4eb8dc403SDave Cobbley# Copyright (C) 2003  Holger Schurig
5eb8dc403SDave Cobbley# Copyright (C) 2003, 2004  Chris Larson
6eb8dc403SDave Cobbley#
7eb8dc403SDave Cobbley# Based on Gentoo's portage.py.
8eb8dc403SDave Cobbley#
9c342db35SBrad Bishop# SPDX-License-Identifier: GPL-2.0-only
10eb8dc403SDave Cobbley#
11eb8dc403SDave Cobbley
12*2f814a6dSPatrick Williams__version__ = "2.9.0"
13eb8dc403SDave Cobbley
14eb8dc403SDave Cobbleyimport sys
15517393d9SAndrew Geisslerif sys.version_info < (3, 8, 0):
16517393d9SAndrew Geissler    raise RuntimeError("Sorry, python 3.8.0 or later is required for this version of bitbake")
17eb8dc403SDave Cobbley
18169d7bccSPatrick Williamsif sys.version_info < (3, 10, 0):
19169d7bccSPatrick Williams    # With python 3.8 and 3.9, we see errors of "libgcc_s.so.1 must be installed for pthread_cancel to work"
20169d7bccSPatrick Williams    # https://stackoverflow.com/questions/64797838/libgcc-s-so-1-must-be-installed-for-pthread-cancel-to-work
21169d7bccSPatrick Williams    # https://bugs.ams1.psf.io/issue42888
22169d7bccSPatrick Williams    # so ensure libgcc_s is loaded early on
23169d7bccSPatrick Williams    import ctypes
24169d7bccSPatrick Williams    libgcc_s = ctypes.CDLL('libgcc_s.so.1')
25eb8dc403SDave Cobbley
26eb8dc403SDave Cobbleyclass BBHandledException(Exception):
27eb8dc403SDave Cobbley    """
28eb8dc403SDave Cobbley    The big dilemma for generic bitbake code is what information to give the user
29eb8dc403SDave Cobbley    when an exception occurs. Any exception inheriting this base exception class
30eb8dc403SDave Cobbley    has already provided information to the user via some 'fired' message type such as
31eb8dc403SDave Cobbley    an explicitly fired event using bb.fire, or a bb.error message. If bitbake
32eb8dc403SDave Cobbley    encounters an exception derived from this class, no backtrace or other information
33eb8dc403SDave Cobbley    will be given to the user, its assumed the earlier event provided the relevant information.
34eb8dc403SDave Cobbley    """
35eb8dc403SDave Cobbley    pass
36eb8dc403SDave Cobbley
37eb8dc403SDave Cobbleyimport os
38eb8dc403SDave Cobbleyimport logging
39eb8dc403SDave Cobbley
40eb8dc403SDave Cobbley
41eb8dc403SDave Cobbleyclass NullHandler(logging.Handler):
42eb8dc403SDave Cobbley    def emit(self, record):
43eb8dc403SDave Cobbley        pass
44eb8dc403SDave Cobbley
455a43b434SAndrew Geisslerclass BBLoggerMixin(object):
465a43b434SAndrew Geissler    def __init__(self, *args, **kwargs):
475a43b434SAndrew Geissler        # Does nothing to allow calling super() from derived classes
485a43b434SAndrew Geissler        pass
495a43b434SAndrew Geissler
505a43b434SAndrew Geissler    def setup_bblogger(self, name):
51eb8dc403SDave Cobbley        if name.split(".")[0] == "BitBake":
52d1e89497SAndrew Geissler            self.debug = self._debug_helper
53d1e89497SAndrew Geissler
54d1e89497SAndrew Geissler    def _debug_helper(self, *args, **kwargs):
55d1e89497SAndrew Geissler        return self.bbdebug(1, *args, **kwargs)
56d1e89497SAndrew Geissler
57d1e89497SAndrew Geissler    def debug2(self, *args, **kwargs):
58d1e89497SAndrew Geissler        return self.bbdebug(2, *args, **kwargs)
59d1e89497SAndrew Geissler
60d1e89497SAndrew Geissler    def debug3(self, *args, **kwargs):
61d1e89497SAndrew Geissler        return self.bbdebug(3, *args, **kwargs)
62eb8dc403SDave Cobbley
63eb8dc403SDave Cobbley    def bbdebug(self, level, msg, *args, **kwargs):
6482c905dcSAndrew Geissler        loglevel = logging.DEBUG - level + 1
6582c905dcSAndrew Geissler        if not bb.event.worker_pid:
6682c905dcSAndrew Geissler            if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
6782c905dcSAndrew Geissler                return
6895ac1b8dSAndrew Geissler            if loglevel < bb.msg.loggerDefaultLogLevel:
6982c905dcSAndrew Geissler                return
7087f5cff0SAndrew Geissler
7187f5cff0SAndrew Geissler        if not isinstance(level, int) or not isinstance(msg, str):
7287f5cff0SAndrew Geissler            mainlogger.warning("Invalid arguments in bbdebug: %s" % repr((level, msg,) + args))
7387f5cff0SAndrew Geissler
7482c905dcSAndrew Geissler        return self.log(loglevel, msg, *args, **kwargs)
75eb8dc403SDave Cobbley
76eb8dc403SDave Cobbley    def plain(self, msg, *args, **kwargs):
77eb8dc403SDave Cobbley        return self.log(logging.INFO + 1, msg, *args, **kwargs)
78eb8dc403SDave Cobbley
79eb8dc403SDave Cobbley    def verbose(self, msg, *args, **kwargs):
80eb8dc403SDave Cobbley        return self.log(logging.INFO - 1, msg, *args, **kwargs)
81eb8dc403SDave Cobbley
821a4b7ee2SBrad Bishop    def verbnote(self, msg, *args, **kwargs):
831a4b7ee2SBrad Bishop        return self.log(logging.INFO + 2, msg, *args, **kwargs)
841a4b7ee2SBrad Bishop
857e0e3c0cSAndrew Geissler    def warnonce(self, msg, *args, **kwargs):
867e0e3c0cSAndrew Geissler        return self.log(logging.WARNING - 1, msg, *args, **kwargs)
877e0e3c0cSAndrew Geissler
887e0e3c0cSAndrew Geissler    def erroronce(self, msg, *args, **kwargs):
897e0e3c0cSAndrew Geissler        return self.log(logging.ERROR - 1, msg, *args, **kwargs)
907e0e3c0cSAndrew Geissler
917e0e3c0cSAndrew Geissler
925a43b434SAndrew GeisslerLogger = logging.getLoggerClass()
935a43b434SAndrew Geisslerclass BBLogger(Logger, BBLoggerMixin):
945a43b434SAndrew Geissler    def __init__(self, name, *args, **kwargs):
955a43b434SAndrew Geissler        self.setup_bblogger(name)
965a43b434SAndrew Geissler        super().__init__(name, *args, **kwargs)
971a4b7ee2SBrad Bishop
98eb8dc403SDave Cobbleylogging.raiseExceptions = False
99eb8dc403SDave Cobbleylogging.setLoggerClass(BBLogger)
100eb8dc403SDave Cobbley
1015a43b434SAndrew Geisslerclass BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
1025a43b434SAndrew Geissler    def __init__(self, logger, *args, **kwargs):
1035a43b434SAndrew Geissler        self.setup_bblogger(logger.name)
1045a43b434SAndrew Geissler        super().__init__(logger, *args, **kwargs)
1055a43b434SAndrew Geissler
1065a43b434SAndrew Geissler    if sys.version_info < (3, 6):
1075a43b434SAndrew Geissler        # These properties were added in Python 3.6. Add them in older versions
1085a43b434SAndrew Geissler        # for compatibility
1095a43b434SAndrew Geissler        @property
1105a43b434SAndrew Geissler        def manager(self):
1115a43b434SAndrew Geissler            return self.logger.manager
1125a43b434SAndrew Geissler
1135a43b434SAndrew Geissler        @manager.setter
1145a43b434SAndrew Geissler        def manager(self, value):
1155a43b434SAndrew Geissler            self.logger.manager = value
1165a43b434SAndrew Geissler
1175a43b434SAndrew Geissler        @property
1185a43b434SAndrew Geissler        def name(self):
1195a43b434SAndrew Geissler            return self.logger.name
1205a43b434SAndrew Geissler
1215a43b434SAndrew Geissler        def __repr__(self):
1225a43b434SAndrew Geissler            logger = self.logger
123c9f7865aSAndrew Geissler            level = logger.getLevelName(logger.getEffectiveLevel())
1245a43b434SAndrew Geissler            return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
1255a43b434SAndrew Geissler
1265a43b434SAndrew Geisslerlogging.LoggerAdapter = BBLoggerAdapter
1275a43b434SAndrew Geissler
128eb8dc403SDave Cobbleylogger = logging.getLogger("BitBake")
129eb8dc403SDave Cobbleylogger.addHandler(NullHandler())
130eb8dc403SDave Cobbleylogger.setLevel(logging.DEBUG - 2)
131eb8dc403SDave Cobbley
132eb8dc403SDave Cobbleymainlogger = logging.getLogger("BitBake.Main")
133eb8dc403SDave Cobbley
1345a43b434SAndrew Geisslerclass PrefixLoggerAdapter(logging.LoggerAdapter):
1355a43b434SAndrew Geissler    def __init__(self, prefix, logger):
1365a43b434SAndrew Geissler        super().__init__(logger, {})
1375a43b434SAndrew Geissler        self.__msg_prefix = prefix
1385a43b434SAndrew Geissler
1395a43b434SAndrew Geissler    def process(self, msg, kwargs):
1405a43b434SAndrew Geissler        return "%s%s" %(self.__msg_prefix, msg), kwargs
1415a43b434SAndrew Geissler
142eb8dc403SDave Cobbley# This has to be imported after the setLoggerClass, as the import of bb.msg
143eb8dc403SDave Cobbley# can result in construction of the various loggers.
144eb8dc403SDave Cobbleyimport bb.msg
145eb8dc403SDave Cobbley
146eb8dc403SDave Cobbleyfrom bb import fetch2 as fetch
147eb8dc403SDave Cobbleysys.modules['bb.fetch'] = sys.modules['bb.fetch2']
148eb8dc403SDave Cobbley
149eb8dc403SDave Cobbley# Messaging convenience functions
150eb8dc403SDave Cobbleydef plain(*args):
151eb8dc403SDave Cobbley    mainlogger.plain(''.join(args))
152eb8dc403SDave Cobbley
153eb8dc403SDave Cobbleydef debug(lvl, *args):
154eb8dc403SDave Cobbley    if isinstance(lvl, str):
155eb8dc403SDave Cobbley        mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
156eb8dc403SDave Cobbley        args = (lvl,) + args
157eb8dc403SDave Cobbley        lvl = 1
158d1e89497SAndrew Geissler    mainlogger.bbdebug(lvl, ''.join(args))
159eb8dc403SDave Cobbley
160eb8dc403SDave Cobbleydef note(*args):
161eb8dc403SDave Cobbley    mainlogger.info(''.join(args))
162eb8dc403SDave Cobbley
1631a4b7ee2SBrad Bishop#
1641a4b7ee2SBrad Bishop# A higher prioity note which will show on the console but isn't a warning
1651a4b7ee2SBrad Bishop#
1661a4b7ee2SBrad Bishop# Something is happening the user should be aware of but they probably did
1671a4b7ee2SBrad Bishop# something to make it happen
1681a4b7ee2SBrad Bishop#
1691a4b7ee2SBrad Bishopdef verbnote(*args):
1701a4b7ee2SBrad Bishop    mainlogger.verbnote(''.join(args))
1711a4b7ee2SBrad Bishop
1721a4b7ee2SBrad Bishop#
1731a4b7ee2SBrad Bishop# Warnings - things the user likely needs to pay attention to and fix
1741a4b7ee2SBrad Bishop#
175eb8dc403SDave Cobbleydef warn(*args):
176eb8dc403SDave Cobbley    mainlogger.warning(''.join(args))
177eb8dc403SDave Cobbley
1787e0e3c0cSAndrew Geisslerdef warnonce(*args):
1797e0e3c0cSAndrew Geissler    mainlogger.warnonce(''.join(args))
1807e0e3c0cSAndrew Geissler
181eb8dc403SDave Cobbleydef error(*args, **kwargs):
182eb8dc403SDave Cobbley    mainlogger.error(''.join(args), extra=kwargs)
183eb8dc403SDave Cobbley
1847e0e3c0cSAndrew Geisslerdef erroronce(*args):
1857e0e3c0cSAndrew Geissler    mainlogger.erroronce(''.join(args))
1867e0e3c0cSAndrew Geissler
187eb8dc403SDave Cobbleydef fatal(*args, **kwargs):
188eb8dc403SDave Cobbley    mainlogger.critical(''.join(args), extra=kwargs)
189eb8dc403SDave Cobbley    raise BBHandledException()
190eb8dc403SDave Cobbley
191eb8dc403SDave Cobbleydef deprecated(func, name=None, advice=""):
192eb8dc403SDave Cobbley    """This is a decorator which can be used to mark functions
193eb8dc403SDave Cobbley    as deprecated. It will result in a warning being emitted
194eb8dc403SDave Cobbley    when the function is used."""
195eb8dc403SDave Cobbley    import warnings
196eb8dc403SDave Cobbley
197eb8dc403SDave Cobbley    if advice:
198eb8dc403SDave Cobbley        advice = ": %s" % advice
199eb8dc403SDave Cobbley    if name is None:
200eb8dc403SDave Cobbley        name = func.__name__
201eb8dc403SDave Cobbley
202eb8dc403SDave Cobbley    def newFunc(*args, **kwargs):
203eb8dc403SDave Cobbley        warnings.warn("Call to deprecated function %s%s." % (name,
204eb8dc403SDave Cobbley                                                             advice),
205eb8dc403SDave Cobbley                      category=DeprecationWarning,
206eb8dc403SDave Cobbley                      stacklevel=2)
207eb8dc403SDave Cobbley        return func(*args, **kwargs)
208eb8dc403SDave Cobbley    newFunc.__name__ = func.__name__
209eb8dc403SDave Cobbley    newFunc.__doc__ = func.__doc__
210eb8dc403SDave Cobbley    newFunc.__dict__.update(func.__dict__)
211eb8dc403SDave Cobbley    return newFunc
212eb8dc403SDave Cobbley
213eb8dc403SDave Cobbley# For compatibility
214eb8dc403SDave Cobbleydef deprecate_import(current, modulename, fromlist, renames = None):
215eb8dc403SDave Cobbley    """Import objects from one module into another, wrapping them with a DeprecationWarning"""
216eb8dc403SDave Cobbley    import sys
217eb8dc403SDave Cobbley
218eb8dc403SDave Cobbley    module = __import__(modulename, fromlist = fromlist)
219eb8dc403SDave Cobbley    for position, objname in enumerate(fromlist):
220eb8dc403SDave Cobbley        obj = getattr(module, objname)
221eb8dc403SDave Cobbley        newobj = deprecated(obj, "{0}.{1}".format(current, objname),
222eb8dc403SDave Cobbley                            "Please use {0}.{1} instead".format(modulename, objname))
223eb8dc403SDave Cobbley        if renames:
224eb8dc403SDave Cobbley            newname = renames[position]
225eb8dc403SDave Cobbley        else:
226eb8dc403SDave Cobbley            newname = objname
227eb8dc403SDave Cobbley
228eb8dc403SDave Cobbley        setattr(sys.modules[current], newname, newobj)
229eb8dc403SDave Cobbley
230