blob: 5e22d34747200a4f6b2befe393238ab6f1390da3 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# BitBake Build System Python Library
3#
4# Copyright (C) 2003 Holger Schurig
5# Copyright (C) 2003, 2004 Chris Larson
6#
7# Based on Gentoo's portage.py.
8#
Brad Bishopc342db32019-05-15 21:57:59 -04009# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011
Patrick Williamsf52e3dd2024-01-26 13:04:43 -060012__version__ = "2.7.2"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050013
14import sys
Andrew Geissler517393d2023-01-13 08:55:19 -060015if sys.version_info < (3, 8, 0):
16 raise RuntimeError("Sorry, python 3.8.0 or later is required for this version of bitbake")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017
Patrick Williams169d7bc2024-01-05 11:33:25 -060018if sys.version_info < (3, 10, 0):
19 # With python 3.8 and 3.9, we see errors of "libgcc_s.so.1 must be installed for pthread_cancel to work"
20 # https://stackoverflow.com/questions/64797838/libgcc-s-so-1-must-be-installed-for-pthread-cancel-to-work
21 # https://bugs.ams1.psf.io/issue42888
22 # so ensure libgcc_s is loaded early on
23 import ctypes
24 libgcc_s = ctypes.CDLL('libgcc_s.so.1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050025
26class BBHandledException(Exception):
27 """
28 The big dilemma for generic bitbake code is what information to give the user
29 when an exception occurs. Any exception inheriting this base exception class
30 has already provided information to the user via some 'fired' message type such as
Andrew Geisslerd1e89492021-02-12 15:35:20 -060031 an explicitly fired event using bb.fire, or a bb.error message. If bitbake
32 encounters an exception derived from this class, no backtrace or other information
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033 will be given to the user, its assumed the earlier event provided the relevant information.
34 """
35 pass
36
37import os
38import logging
39
40
41class NullHandler(logging.Handler):
42 def emit(self, record):
43 pass
44
Andrew Geissler5a43b432020-06-13 10:46:56 -050045class BBLoggerMixin(object):
46 def __init__(self, *args, **kwargs):
47 # Does nothing to allow calling super() from derived classes
48 pass
49
50 def setup_bblogger(self, name):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051 if name.split(".")[0] == "BitBake":
Andrew Geisslerd1e89492021-02-12 15:35:20 -060052 self.debug = self._debug_helper
53
54 def _debug_helper(self, *args, **kwargs):
55 return self.bbdebug(1, *args, **kwargs)
56
57 def debug2(self, *args, **kwargs):
58 return self.bbdebug(2, *args, **kwargs)
59
60 def debug3(self, *args, **kwargs):
61 return self.bbdebug(3, *args, **kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050062
63 def bbdebug(self, level, msg, *args, **kwargs):
Andrew Geissler82c905d2020-04-13 13:39:40 -050064 loglevel = logging.DEBUG - level + 1
65 if not bb.event.worker_pid:
66 if self.name in bb.msg.loggerDefaultDomains and loglevel > (bb.msg.loggerDefaultDomains[self.name]):
67 return
Andrew Geissler95ac1b82021-03-31 14:34:31 -050068 if loglevel < bb.msg.loggerDefaultLogLevel:
Andrew Geissler82c905d2020-04-13 13:39:40 -050069 return
Andrew Geissler87f5cff2022-09-30 13:13:31 -050070
71 if not isinstance(level, int) or not isinstance(msg, str):
72 mainlogger.warning("Invalid arguments in bbdebug: %s" % repr((level, msg,) + args))
73
Andrew Geissler82c905d2020-04-13 13:39:40 -050074 return self.log(loglevel, msg, *args, **kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050075
76 def plain(self, msg, *args, **kwargs):
77 return self.log(logging.INFO + 1, msg, *args, **kwargs)
78
79 def verbose(self, msg, *args, **kwargs):
80 return self.log(logging.INFO - 1, msg, *args, **kwargs)
81
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080082 def verbnote(self, msg, *args, **kwargs):
83 return self.log(logging.INFO + 2, msg, *args, **kwargs)
84
Andrew Geissler7e0e3c02022-02-25 20:34:39 +000085 def warnonce(self, msg, *args, **kwargs):
86 return self.log(logging.WARNING - 1, msg, *args, **kwargs)
87
88 def erroronce(self, msg, *args, **kwargs):
89 return self.log(logging.ERROR - 1, msg, *args, **kwargs)
90
91
Andrew Geissler5a43b432020-06-13 10:46:56 -050092Logger = logging.getLoggerClass()
93class BBLogger(Logger, BBLoggerMixin):
94 def __init__(self, name, *args, **kwargs):
95 self.setup_bblogger(name)
96 super().__init__(name, *args, **kwargs)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080097
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098logging.raiseExceptions = False
99logging.setLoggerClass(BBLogger)
100
Andrew Geissler5a43b432020-06-13 10:46:56 -0500101class BBLoggerAdapter(logging.LoggerAdapter, BBLoggerMixin):
102 def __init__(self, logger, *args, **kwargs):
103 self.setup_bblogger(logger.name)
104 super().__init__(logger, *args, **kwargs)
105
106 if sys.version_info < (3, 6):
107 # These properties were added in Python 3.6. Add them in older versions
108 # for compatibility
109 @property
110 def manager(self):
111 return self.logger.manager
112
113 @manager.setter
114 def manager(self, value):
115 self.logger.manager = value
116
117 @property
118 def name(self):
119 return self.logger.name
120
121 def __repr__(self):
122 logger = self.logger
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500123 level = logger.getLevelName(logger.getEffectiveLevel())
Andrew Geissler5a43b432020-06-13 10:46:56 -0500124 return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
125
126logging.LoggerAdapter = BBLoggerAdapter
127
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128logger = logging.getLogger("BitBake")
129logger.addHandler(NullHandler())
130logger.setLevel(logging.DEBUG - 2)
131
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500132mainlogger = logging.getLogger("BitBake.Main")
133
Andrew Geissler5a43b432020-06-13 10:46:56 -0500134class PrefixLoggerAdapter(logging.LoggerAdapter):
135 def __init__(self, prefix, logger):
136 super().__init__(logger, {})
137 self.__msg_prefix = prefix
138
139 def process(self, msg, kwargs):
140 return "%s%s" %(self.__msg_prefix, msg), kwargs
141
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500142# This has to be imported after the setLoggerClass, as the import of bb.msg
143# can result in construction of the various loggers.
144import bb.msg
145
146from bb import fetch2 as fetch
147sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
148
149# Messaging convenience functions
150def plain(*args):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500151 mainlogger.plain(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500152
153def debug(lvl, *args):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600154 if isinstance(lvl, str):
155 mainlogger.warning("Passed invalid debug level '%s' to bb.debug", lvl)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156 args = (lvl,) + args
157 lvl = 1
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600158 mainlogger.bbdebug(lvl, ''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500159
160def note(*args):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500161 mainlogger.info(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500162
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800163#
164# A higher prioity note which will show on the console but isn't a warning
165#
166# Something is happening the user should be aware of but they probably did
167# something to make it happen
168#
169def verbnote(*args):
170 mainlogger.verbnote(''.join(args))
171
172#
173# Warnings - things the user likely needs to pay attention to and fix
174#
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175def warn(*args):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600176 mainlogger.warning(''.join(args))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000178def warnonce(*args):
179 mainlogger.warnonce(''.join(args))
180
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500181def error(*args, **kwargs):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500182 mainlogger.error(''.join(args), extra=kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500183
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000184def erroronce(*args):
185 mainlogger.erroronce(''.join(args))
186
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500187def fatal(*args, **kwargs):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500188 mainlogger.critical(''.join(args), extra=kwargs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500189 raise BBHandledException()
190
191def deprecated(func, name=None, advice=""):
192 """This is a decorator which can be used to mark functions
193 as deprecated. It will result in a warning being emitted
194 when the function is used."""
195 import warnings
196
197 if advice:
198 advice = ": %s" % advice
199 if name is None:
200 name = func.__name__
201
202 def newFunc(*args, **kwargs):
203 warnings.warn("Call to deprecated function %s%s." % (name,
204 advice),
205 category=DeprecationWarning,
206 stacklevel=2)
207 return func(*args, **kwargs)
208 newFunc.__name__ = func.__name__
209 newFunc.__doc__ = func.__doc__
210 newFunc.__dict__.update(func.__dict__)
211 return newFunc
212
213# For compatibility
214def deprecate_import(current, modulename, fromlist, renames = None):
215 """Import objects from one module into another, wrapping them with a DeprecationWarning"""
216 import sys
217
218 module = __import__(modulename, fromlist = fromlist)
219 for position, objname in enumerate(fromlist):
220 obj = getattr(module, objname)
221 newobj = deprecated(obj, "{0}.{1}".format(current, objname),
222 "Please use {0}.{1} instead".format(modulename, objname))
223 if renames:
224 newname = renames[position]
225 else:
226 newname = objname
227
228 setattr(sys.modules[current], newname, newobj)
229