blob: 36cf74f2968303ba1d3396a643fedb5cf9a452c4 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001try:
2 # Python 2
3 import commands as cmdstatus
4except ImportError:
5 # Python 3
6 import subprocess as cmdstatus
7
8def read_file(filename):
9 try:
10 f = open( filename, "r" )
11 except IOError as reason:
12 return "" # WARNING: can't raise an error now because of the new RDEPENDS handling. This is a bit ugly. :M:
13 else:
14 data = f.read().strip()
15 f.close()
16 return data
17 return None
18
19def ifelse(condition, iftrue = True, iffalse = False):
20 if condition:
21 return iftrue
22 else:
23 return iffalse
24
25def conditional(variable, checkvalue, truevalue, falsevalue, d):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060026 if d.getVar(variable, True) == checkvalue:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050027 return truevalue
28 else:
29 return falsevalue
30
31def less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060032 if float(d.getVar(variable, True)) <= float(checkvalue):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033 return truevalue
34 else:
35 return falsevalue
36
37def version_less_or_equal(variable, checkvalue, truevalue, falsevalue, d):
38 result = bb.utils.vercmp_string(d.getVar(variable,True), checkvalue)
39 if result <= 0:
40 return truevalue
41 else:
42 return falsevalue
43
44def both_contain(variable1, variable2, checkvalue, d):
45 val1 = d.getVar(variable1, True)
46 val2 = d.getVar(variable2, True)
47 val1 = set(val1.split())
48 val2 = set(val2.split())
Patrick Williamsc0f7c042017-02-23 20:41:17 -060049 if isinstance(checkvalue, str):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050050 checkvalue = set(checkvalue.split())
51 else:
52 checkvalue = set(checkvalue)
53 if checkvalue.issubset(val1) and checkvalue.issubset(val2):
54 return " ".join(checkvalue)
55 else:
56 return ""
57
58def set_intersect(variable1, variable2, d):
59 """
60 Expand both variables, interpret them as lists of strings, and return the
61 intersection as a flattened string.
62
63 For example:
64 s1 = "a b c"
65 s2 = "b c d"
66 s3 = set_intersect(s1, s2)
67 => s3 = "b c"
68 """
69 val1 = set(d.getVar(variable1, True).split())
70 val2 = set(d.getVar(variable2, True).split())
71 return " ".join(val1 & val2)
72
73def prune_suffix(var, suffixes, d):
74 # See if var ends with any of the suffixes listed and
75 # remove it if found
76 for suffix in suffixes:
77 if var.endswith(suffix):
78 var = var.replace(suffix, "")
79
80 prefix = d.getVar("MLPREFIX", True)
81 if prefix and var.startswith(prefix):
82 var = var.replace(prefix, "")
83
84 return var
85
86def str_filter(f, str, d):
87 from re import match
Patrick Williamsc0f7c042017-02-23 20:41:17 -060088 return " ".join([x for x in str.split() if match(f, x, 0)])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050089
90def str_filter_out(f, str, d):
91 from re import match
Patrick Williamsc0f7c042017-02-23 20:41:17 -060092 return " ".join([x for x in str.split() if not match(f, x, 0)])
Patrick Williamsc124f4f2015-09-15 14:41:29 -050093
94def param_bool(cfg, field, dflt = None):
95 """Lookup <field> in <cfg> map and convert it to a boolean; take
96 <dflt> when this <field> does not exist"""
97 value = cfg.get(field, dflt)
98 strvalue = str(value).lower()
99 if strvalue in ('yes', 'y', 'true', 't', '1'):
100 return True
101 elif strvalue in ('no', 'n', 'false', 'f', '0'):
102 return False
103 raise ValueError("invalid value for boolean parameter '%s': '%s'" % (field, value))
104
105def inherits(d, *classes):
106 """Return True if the metadata inherits any of the specified classes"""
107 return any(bb.data.inherits_class(cls, d) for cls in classes)
108
109def features_backfill(var,d):
110 # This construct allows the addition of new features to variable specified
111 # as var
112 # Example for var = "DISTRO_FEATURES"
113 # This construct allows the addition of new features to DISTRO_FEATURES
114 # that if not present would disable existing functionality, without
115 # disturbing distributions that have already set DISTRO_FEATURES.
116 # Distributions wanting to elide a value in DISTRO_FEATURES_BACKFILL should
117 # add the feature to DISTRO_FEATURES_BACKFILL_CONSIDERED
118 features = (d.getVar(var, True) or "").split()
119 backfill = (d.getVar(var+"_BACKFILL", True) or "").split()
120 considered = (d.getVar(var+"_BACKFILL_CONSIDERED", True) or "").split()
121
122 addfeatures = []
123 for feature in backfill:
124 if feature not in features and feature not in considered:
125 addfeatures.append(feature)
126
127 if addfeatures:
128 d.appendVar(var, " " + " ".join(addfeatures))
129
130
131def packages_filter_out_system(d):
132 """
133 Return a list of packages from PACKAGES with the "system" packages such as
134 PN-dbg PN-doc PN-locale-eb-gb removed.
135 """
136 pn = d.getVar('PN', True)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600137 blacklist = [pn + suffix for suffix in ('', '-dbg', '-dev', '-doc', '-locale', '-staticdev')]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500138 localepkg = pn + "-locale-"
139 pkgs = []
140
141 for pkg in d.getVar('PACKAGES', True).split():
142 if pkg not in blacklist and localepkg not in pkg:
143 pkgs.append(pkg)
144 return pkgs
145
146def getstatusoutput(cmd):
147 return cmdstatus.getstatusoutput(cmd)
148
149
150def trim_version(version, num_parts=2):
151 """
152 Return just the first <num_parts> of <version>, split by periods. For
153 example, trim_version("1.2.3", 2) will return "1.2".
154 """
155 if type(version) is not str:
156 raise TypeError("Version should be a string")
157 if num_parts < 1:
158 raise ValueError("Cannot split to parts < 1")
159
160 parts = version.split(".")
161 trimmed = ".".join(parts[:num_parts])
162 return trimmed
163
164def cpu_count():
165 import multiprocessing
166 return multiprocessing.cpu_count()
167
168def execute_pre_post_process(d, cmds):
169 if cmds is None:
170 return
171
172 for cmd in cmds.strip().split(';'):
173 cmd = cmd.strip()
174 if cmd != '':
175 bb.note("Executing %s ..." % cmd)
176 bb.build.exec_func(cmd, d)
177
178def multiprocess_exec(commands, function):
179 import signal
180 import multiprocessing
181
182 if not commands:
183 return []
184
185 def init_worker():
186 signal.signal(signal.SIGINT, signal.SIG_IGN)
187
188 nproc = min(multiprocessing.cpu_count(), len(commands))
189 pool = bb.utils.multiprocessingpool(nproc, init_worker)
190 imap = pool.imap(function, commands)
191
192 try:
193 res = list(imap)
194 pool.close()
195 pool.join()
196 results = []
197 for result in res:
198 if result is not None:
199 results.append(result)
200 return results
201
202 except KeyboardInterrupt:
203 pool.terminate()
204 pool.join()
205 raise
206
207def squashspaces(string):
208 import re
209 return re.sub("\s+", " ", string).strip()
210
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500211def format_pkg_list(pkg_dict, ret_format=None):
212 output = []
213
214 if ret_format == "arch":
215 for pkg in sorted(pkg_dict):
216 output.append("%s %s" % (pkg, pkg_dict[pkg]["arch"]))
217 elif ret_format == "file":
218 for pkg in sorted(pkg_dict):
219 output.append("%s %s %s" % (pkg, pkg_dict[pkg]["filename"], pkg_dict[pkg]["arch"]))
220 elif ret_format == "ver":
221 for pkg in sorted(pkg_dict):
222 output.append("%s %s %s" % (pkg, pkg_dict[pkg]["arch"], pkg_dict[pkg]["ver"]))
223 elif ret_format == "deps":
224 for pkg in sorted(pkg_dict):
225 for dep in pkg_dict[pkg]["deps"]:
226 output.append("%s|%s" % (pkg, dep))
227 else:
228 for pkg in sorted(pkg_dict):
229 output.append(pkg)
230
231 return '\n'.join(output)
232
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500233def host_gcc_version(d):
234 import re, subprocess
235
236 compiler = d.getVar("BUILD_CC", True)
237
238 try:
239 env = os.environ.copy()
240 env["PATH"] = d.getVar("PATH", True)
241 output = subprocess.check_output("%s --version" % compiler, shell=True, env=env).decode("utf-8")
242 except subprocess.CalledProcessError as e:
243 bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
244
245 match = re.match(".* (\d\.\d)\.\d.*", output.split('\n')[0])
246 if not match:
247 bb.fatal("Can't get compiler version from %s --version output" % compiler)
248
249 version = match.group(1)
250 return "-%s" % version if version in ("4.8", "4.9") else ""
251
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500252#
253# Python 2.7 doesn't have threaded pools (just multiprocessing)
254# so implement a version here
255#
256
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600257from queue import Queue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500258from threading import Thread
259
260class ThreadedWorker(Thread):
261 """Thread executing tasks from a given tasks queue"""
262 def __init__(self, tasks, worker_init, worker_end):
263 Thread.__init__(self)
264 self.tasks = tasks
265 self.daemon = True
266
267 self.worker_init = worker_init
268 self.worker_end = worker_end
269
270 def run(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600271 from queue import Empty
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500272
273 if self.worker_init is not None:
274 self.worker_init(self)
275
276 while True:
277 try:
278 func, args, kargs = self.tasks.get(block=False)
279 except Empty:
280 if self.worker_end is not None:
281 self.worker_end(self)
282 break
283
284 try:
285 func(self, *args, **kargs)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600286 except Exception as e:
287 print(e)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288 finally:
289 self.tasks.task_done()
290
291class ThreadedPool:
292 """Pool of threads consuming tasks from a queue"""
293 def __init__(self, num_workers, num_tasks, worker_init=None,
294 worker_end=None):
295 self.tasks = Queue(num_tasks)
296 self.workers = []
297
298 for _ in range(num_workers):
299 worker = ThreadedWorker(self.tasks, worker_init, worker_end)
300 self.workers.append(worker)
301
302 def start(self):
303 for worker in self.workers:
304 worker.start()
305
306 def add_task(self, func, *args, **kargs):
307 """Add a task to the queue"""
308 self.tasks.put((func, args, kargs))
309
310 def wait_completion(self):
311 """Wait for completion of all the tasks in the queue"""
312 self.tasks.join()
313 for worker in self.workers:
314 worker.join()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500315
316def write_ld_so_conf(d):
317 # Some utils like prelink may not have the correct target library paths
318 # so write an ld.so.conf to help them
319 ldsoconf = d.expand("${STAGING_DIR_TARGET}${sysconfdir}/ld.so.conf")
320 if os.path.exists(ldsoconf):
321 bb.utils.remove(ldsoconf)
322 bb.utils.mkdirhier(os.path.dirname(ldsoconf))
323 with open(ldsoconf, "w") as f:
324 f.write(d.getVar("base_libdir", True) + '\n')
325 f.write(d.getVar("libdir", True) + '\n')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600326
327class ImageQAFailed(bb.build.FuncFailed):
328 def __init__(self, description, name=None, logfile=None):
329 self.description = description
330 self.name = name
331 self.logfile=logfile
332
333 def __str__(self):
334 msg = 'Function failed: %s' % self.name
335 if self.description:
336 msg = msg + ' (%s)' % self.description
337
338 return msg