blob: 13f4271da04fd09115275199b89207b77f1a6cf8 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: GPL-2.0-only
3#
4
Brad Bishop6e60e8b2018-02-01 10:27:11 -05005import subprocess
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08006import multiprocessing
7import traceback
Patrick Williamsc124f4f2015-09-15 14:41:29 -05008
9def read_file(filename):
10 try:
11 f = open( filename, "r" )
12 except IOError as reason:
13 return "" # WARNING: can't raise an error now because of the new RDEPENDS handling. This is a bit ugly. :M:
14 else:
15 data = f.read().strip()
16 f.close()
17 return data
18 return None
19
20def ifelse(condition, iftrue = True, iffalse = False):
21 if condition:
22 return iftrue
23 else:
24 return iffalse
25
26def conditional(variable, checkvalue, truevalue, falsevalue, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050027 if d.getVar(variable) == checkvalue:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028 return truevalue
29 else:
30 return falsevalue
31
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080032def vartrue(var, iftrue, iffalse, d):
33 import oe.types
34 if oe.types.boolean(d.getVar(var)):
35 return iftrue
36 else:
37 return iffalse
38
Patrick Williamsc124f4f2015-09-15 14:41:29 -050039def less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050040 if float(d.getVar(variable)) <= float(checkvalue):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041 return truevalue
42 else:
43 return falsevalue
44
45def version_less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050046 result = bb.utils.vercmp_string(d.getVar(variable), checkvalue)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047 if result <= 0:
48 return truevalue
49 else:
50 return falsevalue
51
52def both_contain(variable1, variable2, checkvalue, d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050053 val1 = d.getVar(variable1)
54 val2 = d.getVar(variable2)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050055 val1 = set(val1.split())
56 val2 = set(val2.split())
Patrick Williamsc0f7c042017-02-23 20:41:17 -060057 if isinstance(checkvalue, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 checkvalue = set(checkvalue.split())
59 else:
60 checkvalue = set(checkvalue)
61 if checkvalue.issubset(val1) and checkvalue.issubset(val2):
62 return " ".join(checkvalue)
63 else:
64 return ""
65
66def set_intersect(variable1, variable2, d):
67 """
68 Expand both variables, interpret them as lists of strings, and return the
69 intersection as a flattened string.
70
71 For example:
72 s1 = "a b c"
73 s2 = "b c d"
74 s3 = set_intersect(s1, s2)
75 => s3 = "b c"
76 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -050077 val1 = set(d.getVar(variable1).split())
78 val2 = set(d.getVar(variable2).split())
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079 return " ".join(val1 & val2)
80
81def prune_suffix(var, suffixes, d):
82 # See if var ends with any of the suffixes listed and
83 # remove it if found
84 for suffix in suffixes:
Brad Bishopd89cb5f2019-04-10 09:02:41 -040085 if suffix and var.endswith(suffix):
86 var = var[:-len(suffix)]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050087
Brad Bishop6e60e8b2018-02-01 10:27:11 -050088 prefix = d.getVar("MLPREFIX")
Patrick Williamsc124f4f2015-09-15 14:41:29 -050089 if prefix and var.startswith(prefix):
Brad Bishopd89cb5f2019-04-10 09:02:41 -040090 var = var[len(prefix):]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091
92 return var
93
94def str_filter(f, str, d):
95 from re import match
Patrick Williamsc0f7c042017-02-23 20:41:17 -060096 return " ".join([x for x in str.split() if match(f, x, 0)])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097
98def str_filter_out(f, str, d):
99 from re import match
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600100 return " ".join([x for x in str.split() if not match(f, x, 0)])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500102def build_depends_string(depends, task):
103 """Append a taskname to a string of dependencies as used by the [depends] flag"""
104 return " ".join(dep + ":" + task for dep in depends.split())
105
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500106def inherits(d, *classes):
107 """Return True if the metadata inherits any of the specified classes"""
108 return any(bb.data.inherits_class(cls, d) for cls in classes)
109
110def features_backfill(var,d):
111 # This construct allows the addition of new features to variable specified
112 # as var
113 # Example for var = "DISTRO_FEATURES"
114 # This construct allows the addition of new features to DISTRO_FEATURES
115 # that if not present would disable existing functionality, without
116 # disturbing distributions that have already set DISTRO_FEATURES.
117 # Distributions wanting to elide a value in DISTRO_FEATURES_BACKFILL should
118 # add the feature to DISTRO_FEATURES_BACKFILL_CONSIDERED
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500119 features = (d.getVar(var) or "").split()
120 backfill = (d.getVar(var+"_BACKFILL") or "").split()
121 considered = (d.getVar(var+"_BACKFILL_CONSIDERED") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500122
123 addfeatures = []
124 for feature in backfill:
125 if feature not in features and feature not in considered:
126 addfeatures.append(feature)
127
128 if addfeatures:
129 d.appendVar(var, " " + " ".join(addfeatures))
130
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500131def all_distro_features(d, features, truevalue="1", falsevalue=""):
132 """
133 Returns truevalue if *all* given features are set in DISTRO_FEATURES,
134 else falsevalue. The features can be given as single string or anything
135 that can be turned into a set.
136
137 This is a shorter, more flexible version of
138 bb.utils.contains("DISTRO_FEATURES", features, truevalue, falsevalue, d).
139
140 Without explicit true/false values it can be used directly where
141 Python expects a boolean:
142 if oe.utils.all_distro_features(d, "foo bar"):
143 bb.fatal("foo and bar are mutually exclusive DISTRO_FEATURES")
144
145 With just a truevalue, it can be used to include files that are meant to be
146 used only when requested via DISTRO_FEATURES:
147 require ${@ oe.utils.all_distro_features(d, "foo bar", "foo-and-bar.inc")
148 """
149 return bb.utils.contains("DISTRO_FEATURES", features, truevalue, falsevalue, d)
150
151def any_distro_features(d, features, truevalue="1", falsevalue=""):
152 """
153 Returns truevalue if at least *one* of the given features is set in DISTRO_FEATURES,
154 else falsevalue. The features can be given as single string or anything
155 that can be turned into a set.
156
157 This is a shorter, more flexible version of
158 bb.utils.contains_any("DISTRO_FEATURES", features, truevalue, falsevalue, d).
159
160 Without explicit true/false values it can be used directly where
161 Python expects a boolean:
162 if not oe.utils.any_distro_features(d, "foo bar"):
163 bb.fatal("foo, bar or both must be set in DISTRO_FEATURES")
164
165 With just a truevalue, it can be used to include files that are meant to be
166 used only when requested via DISTRO_FEATURES:
167 require ${@ oe.utils.any_distro_features(d, "foo bar", "foo-or-bar.inc")
168
169 """
170 return bb.utils.contains_any("DISTRO_FEATURES", features, truevalue, falsevalue, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500171
Andrew Geissler82c905d2020-04-13 13:39:40 -0500172def parallel_make(d, makeinst=False):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400173 """
174 Return the integer value for the number of parallel threads to use when
175 building, scraped out of PARALLEL_MAKE. If no parallelization option is
176 found, returns None
177
178 e.g. if PARALLEL_MAKE = "-j 10", this will return 10 as an integer.
179 """
Andrew Geissler82c905d2020-04-13 13:39:40 -0500180 if makeinst:
181 pm = (d.getVar('PARALLEL_MAKEINST') or '').split()
182 else:
183 pm = (d.getVar('PARALLEL_MAKE') or '').split()
Brad Bishop316dfdd2018-06-25 12:45:53 -0400184 # look for '-j' and throw other options (e.g. '-l') away
185 while pm:
186 opt = pm.pop(0)
187 if opt == '-j':
188 v = pm.pop(0)
189 elif opt.startswith('-j'):
190 v = opt[2:].strip()
191 else:
192 continue
193
194 return int(v)
195
196 return None
197
Andrew Geissler82c905d2020-04-13 13:39:40 -0500198def parallel_make_argument(d, fmt, limit=None, makeinst=False):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400199 """
200 Helper utility to construct a parallel make argument from the number of
201 parallel threads specified in PARALLEL_MAKE.
202
203 Returns the input format string `fmt` where a single '%d' will be expanded
204 with the number of parallel threads to use. If `limit` is specified, the
205 number of parallel threads will be no larger than it. If no parallelization
206 option is found in PARALLEL_MAKE, returns an empty string
207
208 e.g. if PARALLEL_MAKE = "-j 10", parallel_make_argument(d, "-n %d") will return
209 "-n 10"
210 """
Andrew Geissler82c905d2020-04-13 13:39:40 -0500211 v = parallel_make(d, makeinst)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400212 if v:
213 if limit:
214 v = min(limit, v)
215 return fmt % v
216 return ''
217
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500218def packages_filter_out_system(d):
219 """
220 Return a list of packages from PACKAGES with the "system" packages such as
221 PN-dbg PN-doc PN-locale-eb-gb removed.
222 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500223 pn = d.getVar('PN')
Brad Bishop19323692019-04-05 15:28:33 -0400224 blacklist = [pn + suffix for suffix in ('', '-dbg', '-dev', '-doc', '-locale', '-staticdev', '-src')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500225 localepkg = pn + "-locale-"
226 pkgs = []
227
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500228 for pkg in d.getVar('PACKAGES').split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 if pkg not in blacklist and localepkg not in pkg:
230 pkgs.append(pkg)
231 return pkgs
232
233def getstatusoutput(cmd):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500234 return subprocess.getstatusoutput(cmd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235
236
237def trim_version(version, num_parts=2):
238 """
239 Return just the first <num_parts> of <version>, split by periods. For
240 example, trim_version("1.2.3", 2) will return "1.2".
241 """
242 if type(version) is not str:
243 raise TypeError("Version should be a string")
244 if num_parts < 1:
245 raise ValueError("Cannot split to parts < 1")
246
247 parts = version.split(".")
248 trimmed = ".".join(parts[:num_parts])
249 return trimmed
250
Andrew Geissler82c905d2020-04-13 13:39:40 -0500251def cpu_count(at_least=1):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500252 import multiprocessing
Andrew Geissler82c905d2020-04-13 13:39:40 -0500253 cpus = multiprocessing.cpu_count()
254 return max(cpus, at_least)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500255
256def execute_pre_post_process(d, cmds):
257 if cmds is None:
258 return
259
260 for cmd in cmds.strip().split(';'):
261 cmd = cmd.strip()
262 if cmd != '':
263 bb.note("Executing %s ..." % cmd)
264 bb.build.exec_func(cmd, d)
265
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800266# For each item in items, call the function 'target' with item as the first
267# argument, extraargs as the other arguments and handle any exceptions in the
268# parent thread
269def multiprocess_launch(target, items, d, extraargs=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500270
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800271 class ProcessLaunch(multiprocessing.Process):
272 def __init__(self, *args, **kwargs):
273 multiprocessing.Process.__init__(self, *args, **kwargs)
274 self._pconn, self._cconn = multiprocessing.Pipe()
275 self._exception = None
276 self._result = None
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500277
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800278 def run(self):
279 try:
280 ret = self._target(*self._args, **self._kwargs)
281 self._cconn.send((None, ret))
282 except Exception as e:
283 tb = traceback.format_exc()
284 self._cconn.send((e, tb))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500285
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800286 def update(self):
287 if self._pconn.poll():
288 (e, tb) = self._pconn.recv()
289 if e is not None:
290 self._exception = (e, tb)
291 else:
292 self._result = tb
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500293
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800294 @property
295 def exception(self):
296 self.update()
297 return self._exception
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500298
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800299 @property
300 def result(self):
301 self.update()
302 return self._result
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800304 max_process = int(d.getVar("BB_NUMBER_THREADS") or os.cpu_count() or 1)
305 launched = []
306 errors = []
307 results = []
308 items = list(items)
309 while (items and not errors) or launched:
310 if not errors and items and len(launched) < max_process:
311 args = (items.pop(),)
312 if extraargs is not None:
313 args = args + extraargs
314 p = ProcessLaunch(target=target, args=args)
315 p.start()
316 launched.append(p)
317 for q in launched:
Brad Bishop19323692019-04-05 15:28:33 -0400318 # Have to manually call update() to avoid deadlocks. The pipe can be full and
319 # transfer stalled until we try and read the results object but the subprocess won't exit
320 # as it still has data to write (https://bugs.python.org/issue8426)
321 q.update()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800322 # The finished processes are joined when calling is_alive()
323 if not q.is_alive():
324 if q.exception:
325 errors.append(q.exception)
326 if q.result:
327 results.append(q.result)
328 launched.remove(q)
329 # Paranoia doesn't hurt
330 for p in launched:
331 p.join()
332 if errors:
333 msg = ""
334 for (e, tb) in errors:
Brad Bishopc342db32019-05-15 21:57:59 -0400335 if isinstance(e, subprocess.CalledProcessError) and e.output:
336 msg = msg + str(e) + "\n"
337 msg = msg + "Subprocess output:"
338 msg = msg + e.output.decode("utf-8", errors="ignore")
339 else:
340 msg = msg + str(e) + ": " + str(tb) + "\n"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800341 bb.fatal("Fatal errors occurred in subprocesses:\n%s" % msg)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500342 return results
343
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500344def squashspaces(string):
345 import re
Brad Bishop19323692019-04-05 15:28:33 -0400346 return re.sub(r"\s+", " ", string).strip()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500347
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500348def format_pkg_list(pkg_dict, ret_format=None):
349 output = []
350
351 if ret_format == "arch":
352 for pkg in sorted(pkg_dict):
353 output.append("%s %s" % (pkg, pkg_dict[pkg]["arch"]))
354 elif ret_format == "file":
355 for pkg in sorted(pkg_dict):
356 output.append("%s %s %s" % (pkg, pkg_dict[pkg]["filename"], pkg_dict[pkg]["arch"]))
357 elif ret_format == "ver":
358 for pkg in sorted(pkg_dict):
359 output.append("%s %s %s" % (pkg, pkg_dict[pkg]["arch"], pkg_dict[pkg]["ver"]))
360 elif ret_format == "deps":
361 for pkg in sorted(pkg_dict):
362 for dep in pkg_dict[pkg]["deps"]:
363 output.append("%s|%s" % (pkg, dep))
364 else:
365 for pkg in sorted(pkg_dict):
366 output.append(pkg)
367
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800368 output_str = '\n'.join(output)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500369
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800370 if output_str:
371 # make sure last line is newline terminated
372 output_str += '\n'
373
374 return output_str
375
Andrew Geissler82c905d2020-04-13 13:39:40 -0500376
377# Helper function to get the host compiler version
378# Do not assume the compiler is gcc
379def get_host_compiler_version(d, taskcontextonly=False):
380 import re, subprocess
381
382 if taskcontextonly and d.getVar('BB_WORKERCONTEXT') != '1':
383 return
384
385 compiler = d.getVar("BUILD_CC")
386 # Get rid of ccache since it is not present when parsing.
387 if compiler.startswith('ccache '):
388 compiler = compiler[7:]
389 try:
390 env = os.environ.copy()
391 # datastore PATH does not contain session PATH as set by environment-setup-...
392 # this breaks the install-buildtools use-case
393 # env["PATH"] = d.getVar("PATH")
394 output = subprocess.check_output("%s --version" % compiler, \
395 shell=True, env=env, stderr=subprocess.STDOUT).decode("utf-8")
396 except subprocess.CalledProcessError as e:
397 bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
398
399 match = re.match(r".* (\d+\.\d+)\.\d+.*", output.split('\n')[0])
400 if not match:
401 bb.fatal("Can't get compiler version from %s --version output" % compiler)
402
403 version = match.group(1)
404 return compiler, version
405
406
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800407def host_gcc_version(d, taskcontextonly=False):
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500408 import re, subprocess
409
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800410 if taskcontextonly and d.getVar('BB_WORKERCONTEXT') != '1':
411 return
412
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500413 compiler = d.getVar("BUILD_CC")
Brad Bishop19323692019-04-05 15:28:33 -0400414 # Get rid of ccache since it is not present when parsing.
415 if compiler.startswith('ccache '):
416 compiler = compiler[7:]
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500417 try:
418 env = os.environ.copy()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500419 env["PATH"] = d.getVar("PATH")
Brad Bishop19323692019-04-05 15:28:33 -0400420 output = subprocess.check_output("%s --version" % compiler, \
421 shell=True, env=env, stderr=subprocess.STDOUT).decode("utf-8")
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500422 except subprocess.CalledProcessError as e:
423 bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
424
Andrew Geissler82c905d2020-04-13 13:39:40 -0500425 match = re.match(r".* (\d+\.\d+)\.\d+.*", output.split('\n')[0])
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500426 if not match:
427 bb.fatal("Can't get compiler version from %s --version output" % compiler)
428
429 version = match.group(1)
430 return "-%s" % version if version in ("4.8", "4.9") else ""
431
Brad Bishop316dfdd2018-06-25 12:45:53 -0400432
433def get_multilib_datastore(variant, d):
434 localdata = bb.data.createCopy(d)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800435 if variant:
436 overrides = localdata.getVar("OVERRIDES", False) + ":virtclass-multilib-" + variant
437 localdata.setVar("OVERRIDES", overrides)
438 localdata.setVar("MLPREFIX", variant + "-")
439 else:
440 origdefault = localdata.getVar("DEFAULTTUNE_MULTILIB_ORIGINAL")
441 if origdefault:
442 localdata.setVar("DEFAULTTUNE", origdefault)
443 overrides = localdata.getVar("OVERRIDES", False).split(":")
444 overrides = ":".join([x for x in overrides if not x.startswith("virtclass-multilib-")])
445 localdata.setVar("OVERRIDES", overrides)
446 localdata.setVar("MLPREFIX", "")
Brad Bishop316dfdd2018-06-25 12:45:53 -0400447 return localdata
448
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500449#
450# Python 2.7 doesn't have threaded pools (just multiprocessing)
451# so implement a version here
452#
453
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600454from queue import Queue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500455from threading import Thread
456
457class ThreadedWorker(Thread):
458 """Thread executing tasks from a given tasks queue"""
459 def __init__(self, tasks, worker_init, worker_end):
460 Thread.__init__(self)
461 self.tasks = tasks
462 self.daemon = True
463
464 self.worker_init = worker_init
465 self.worker_end = worker_end
466
467 def run(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600468 from queue import Empty
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500469
470 if self.worker_init is not None:
471 self.worker_init(self)
472
473 while True:
474 try:
475 func, args, kargs = self.tasks.get(block=False)
476 except Empty:
477 if self.worker_end is not None:
478 self.worker_end(self)
479 break
480
481 try:
482 func(self, *args, **kargs)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600483 except Exception as e:
484 print(e)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500485 finally:
486 self.tasks.task_done()
487
488class ThreadedPool:
489 """Pool of threads consuming tasks from a queue"""
490 def __init__(self, num_workers, num_tasks, worker_init=None,
491 worker_end=None):
492 self.tasks = Queue(num_tasks)
493 self.workers = []
494
495 for _ in range(num_workers):
496 worker = ThreadedWorker(self.tasks, worker_init, worker_end)
497 self.workers.append(worker)
498
499 def start(self):
500 for worker in self.workers:
501 worker.start()
502
503 def add_task(self, func, *args, **kargs):
504 """Add a task to the queue"""
505 self.tasks.put((func, args, kargs))
506
507 def wait_completion(self):
508 """Wait for completion of all the tasks in the queue"""
509 self.tasks.join()
510 for worker in self.workers:
511 worker.join()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500512
513def write_ld_so_conf(d):
514 # Some utils like prelink may not have the correct target library paths
515 # so write an ld.so.conf to help them
516 ldsoconf = d.expand("${STAGING_DIR_TARGET}${sysconfdir}/ld.so.conf")
517 if os.path.exists(ldsoconf):
518 bb.utils.remove(ldsoconf)
519 bb.utils.mkdirhier(os.path.dirname(ldsoconf))
520 with open(ldsoconf, "w") as f:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500521 f.write(d.getVar("base_libdir") + '\n')
522 f.write(d.getVar("libdir") + '\n')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600523
Brad Bishop08902b02019-08-20 09:16:51 -0400524class ImageQAFailed(Exception):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600525 def __init__(self, description, name=None, logfile=None):
526 self.description = description
527 self.name = name
528 self.logfile=logfile
529
530 def __str__(self):
531 msg = 'Function failed: %s' % self.name
532 if self.description:
533 msg = msg + ' (%s)' % self.description
534
535 return msg
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800536
Brad Bishop19323692019-04-05 15:28:33 -0400537def sh_quote(string):
538 import shlex
539 return shlex.quote(string)