diff options
Diffstat (limited to 'meta-oe/classes/check-version-mismatch.bbclass')
-rw-r--r-- | meta-oe/classes/check-version-mismatch.bbclass | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/meta-oe/classes/check-version-mismatch.bbclass b/meta-oe/classes/check-version-mismatch.bbclass new file mode 100644 index 0000000000..f735280d7a --- /dev/null +++ b/meta-oe/classes/check-version-mismatch.bbclass | |||
@@ -0,0 +1,471 @@ | |||
1 | QEMU_OPTIONS = "-r ${OLDEST_KERNEL} ${@d.getVar("QEMU_EXTRAOPTIONS:tune-%s" % d.getVar('TUNE_PKGARCH')) or ""}" | ||
2 | QEMU_OPTIONS[vardeps] += "QEMU_EXTRAOPTIONS:tune-${TUNE_PKGARCH}" | ||
3 | |||
4 | ENABLE_VERSION_MISMATCH_CHECK ?= "${@'1' if bb.utils.contains('MACHINE_FEATURES', 'qemu-usermode', True, False, d) else '0'}" | ||
5 | DEBUG_VERSION_MISMATCH_CHECK ?= "1" | ||
6 | CHECK_VERSION_PV ?= "" | ||
7 | |||
8 | DEPENDS:append:class-target = "${@' qemu-native' if bb.utils.to_boolean(d.getVar('ENABLE_VERSION_MISMATCH_CHECK')) else ''}" | ||
9 | |||
10 | QEMU_EXEC ?= "${@oe.qemu.qemu_wrapper_cmdline(d, '${STAGING_DIR_HOST}', ['${STAGING_DIR_HOST}${libdir}','${STAGING_DIR_HOST}${base_libdir}', '${PKGD}${libdir}', '${PKGD}${base_libdir}'])}" | ||
11 | |||
12 | python do_package_check_version_mismatch() { | ||
13 | import re | ||
14 | import subprocess | ||
15 | import shutil | ||
16 | import signal | ||
17 | import glob | ||
18 | |||
19 | classes_skip = ["nopackage", "image", "native", "cross", "crosssdk", "cross-canadian"] | ||
20 | for cs in classes_skip: | ||
21 | if bb.data.inherits_class(cs, d): | ||
22 | bb.note(f"Skip do_package_check_version_mismatch as {cs} is inherited.") | ||
23 | return | ||
24 | |||
25 | if not bb.utils.to_boolean(d.getVar('ENABLE_VERSION_MISMATCH_CHECK')): | ||
26 | bb.note("Skip do_package_check_version_mismatch as ENABLE_VERSION_MISMATCH_CHECK is disabled.") | ||
27 | return | ||
28 | |||
29 | __regexp_version_broad_match__ = re.compile(r"(?:\s|^|-|_|/|=| go|\()" + | ||
30 | r"(?P<version>v?[0-9][0-9.][0-9+.\-_~\(\)]*?|UNKNOWN)" + | ||
31 | r"(?:[+\-]release.*|[+\-]stable.*|)" + | ||
32 | r"(?P<extra>[+\-]unknown|[+\-]dirty|[+\-]rc?\d{1,3}|\+cargo-[0-9.]+|" + | ||
33 | r"[a-z]|-?[pP][0-9]{1,3}|-?beta[^\s]*|-?alpha[^\s]*|)" + | ||
34 | r"(?P<extra2>[+\-]dev|[+\-]devel|)" + | ||
35 | r"(?:,|:|\.|\)|-[0-9a-g]{6,42}|)" + | ||
36 | r"(?=\s|$)" | ||
37 | ) | ||
38 | __regexp_exclude_year__ = re.compile(r"^(19|20)[0-9]{2}$") | ||
39 | __regexp_single_number_ending_with_dot__ = re.compile(r"^\d\.$") | ||
40 | |||
41 | def is_shared_library(filepath): | ||
42 | return re.match(r'.*\.so(\.\d+)*$', filepath) is not None | ||
43 | |||
44 | def get_possible_versions(output_contents, full_cmd=None, max_lines=None): | ||
45 | # | ||
46 | # Algorithm: | ||
47 | # 1. Check version line by line. | ||
48 | # 2. Skip some lines which we know that do not contain version information, e.g., License, Copyright. | ||
49 | # 3. Do broad match, finding all possible versions. | ||
50 | # 4. If there's a version found by any match, do exclude match (e.g., exclude years) | ||
51 | # 5. If there's a valid version, do stripping and converting and then add to possible_versions. | ||
52 | # 6. Return possible_versions | ||
53 | # | ||
54 | possible_versions = [] | ||
55 | content_lines = output_contents.split("\n") | ||
56 | if max_lines: | ||
57 | content_lines = content_lines[0:max_lines] | ||
58 | if full_cmd: | ||
59 | base_cmd = os.path.basename(full_cmd) | ||
60 | __regex_help_format__ = re.compile(r"-[^\s].*") | ||
61 | for line in content_lines: | ||
62 | line = line.strip() | ||
63 | # skip help lines | ||
64 | if __regex_help_format__.match(line): | ||
65 | continue | ||
66 | # avoid command itself affecting output | ||
67 | if full_cmd: | ||
68 | if line.startswith(base_cmd): | ||
69 | line = line[len(base_cmd):] | ||
70 | elif line.startswith(full_cmd): | ||
71 | line = line[len(full_cmd):] | ||
72 | # skip specific lines | ||
73 | skip_keywords_start = ["copyright", "license", "compiled", "build", "built"] | ||
74 | skip_line = False | ||
75 | for sks in skip_keywords_start: | ||
76 | if line.lower().startswith(sks): | ||
77 | skip_line = True | ||
78 | break | ||
79 | if skip_line: | ||
80 | continue | ||
81 | |||
82 | # try broad match | ||
83 | for match in __regexp_version_broad_match__.finditer(line): | ||
84 | version = match.group("version") | ||
85 | #print(f"version = {version}") | ||
86 | # do exclude match | ||
87 | exclude_match = __regexp_exclude_year__.match(version) | ||
88 | if exclude_match: | ||
89 | continue | ||
90 | exclude_match = __regexp_single_number_ending_with_dot__.match(version) | ||
91 | if exclude_match: | ||
92 | continue | ||
93 | # do some stripping and converting | ||
94 | if version.startswith("("): | ||
95 | version = version[1:-1] | ||
96 | if version.startswith("v"): | ||
97 | version = version[1:] | ||
98 | if version.endswith(")") and "(" not in version: | ||
99 | version = version[:-1] | ||
100 | if not version.endswith(")") and "(" in version: | ||
101 | version = version.split('(')[0] | ||
102 | # handle extra version info | ||
103 | version = version + match.group("extra") + match.group("extra2") | ||
104 | possible_versions.append(version) | ||
105 | return possible_versions | ||
106 | |||
107 | def is_version_mismatch(rvs, pv): | ||
108 | got_match = False | ||
109 | if pv.startswith("git"): | ||
110 | return False | ||
111 | if "-pre" in pv: | ||
112 | pv = pv.split("-pre")[0] | ||
113 | if pv.startswith("v"): | ||
114 | pv = pv[1:] | ||
115 | for rv in rvs: | ||
116 | if rv == pv: | ||
117 | got_match = True | ||
118 | break | ||
119 | pv = pv.split("+git")[0] | ||
120 | # handle % character in pv which means matching any chars | ||
121 | if '%' in pv: | ||
122 | escaped_pv = re.escape(pv) | ||
123 | regex_pattern = escaped_pv.replace('%', '.*') | ||
124 | regex_pattern = f'^{regex_pattern}$' | ||
125 | if re.fullmatch(regex_pattern, rv): | ||
126 | got_match = True | ||
127 | break | ||
128 | else: | ||
129 | continue | ||
130 | # handle cases such as 2.36.0-r0 v.s. 2.36.0 | ||
131 | if "-r" in rv: | ||
132 | rv = rv.split("-r")[0] | ||
133 | chars_to_replace = ["-", "+", "_", "~"] | ||
134 | # convert to use "." as the version seperator | ||
135 | for cr in chars_to_replace: | ||
136 | rv = rv.replace(cr, ".") | ||
137 | pv = pv.replace(cr, ".") | ||
138 | if rv == pv: | ||
139 | got_match = True | ||
140 | break | ||
141 | # handle case such as 5.2.37(1) v.s. 5.2.37 | ||
142 | if "(" in rv: | ||
143 | rv = rv.split("(")[0] | ||
144 | if rv == pv: | ||
145 | got_match = True | ||
146 | break | ||
147 | # handle case such as 4.4.3p1 | ||
148 | if "p" in pv and "p" in rv.lower(): | ||
149 | pv = pv.lower().replace(".p", "p") | ||
150 | rv = rv.lower().replace(".p", "p") | ||
151 | if pv == rv: | ||
152 | got_match = True | ||
153 | break | ||
154 | # handle cases such as 6.00 v.s. 6.0 | ||
155 | if rv.startswith(pv): | ||
156 | if rv == pv + "0" or rv == pv + ".0": | ||
157 | got_match = True | ||
158 | break | ||
159 | elif pv.startswith(rv): | ||
160 | if pv == rv + "0" or pv == rv + ".0": | ||
161 | got_match = True | ||
162 | break | ||
163 | # handle cases such as 21306 v.s. 2.13.6 | ||
164 | if "." in pv and not "." in rv: | ||
165 | pv_components = pv.split(".") | ||
166 | if rv.startswith(pv_components[0]): | ||
167 | pv_num = 0 | ||
168 | for i in range(0, len(pv_components)): | ||
169 | pv_num = pv_num * 100 + int(pv_components[i]) | ||
170 | if pv_num == int(rv): | ||
171 | got_match = True | ||
172 | break | ||
173 | if got_match: | ||
174 | return False | ||
175 | else: | ||
176 | return True | ||
177 | |||
178 | def is_elf_binary(fexec): | ||
179 | fexec_real = os.path.realpath(fexec) | ||
180 | elf = oe.qa.ELFFile(fexec_real) | ||
181 | try: | ||
182 | elf.open() | ||
183 | elf.close() | ||
184 | return True | ||
185 | except: | ||
186 | return False | ||
187 | |||
188 | def get_shebang(fexec): | ||
189 | try: | ||
190 | with open(fexec, 'r') as f: | ||
191 | first_line = f.readline().strip() | ||
192 | if first_line.startswith("#!"): | ||
193 | return first_line | ||
194 | else: | ||
195 | return None | ||
196 | except Exception as e: | ||
197 | return None | ||
198 | |||
199 | def get_interpreter_from_shebang(shebang): | ||
200 | if not shebang: | ||
201 | return None | ||
202 | hosttools_path = d.getVar("TMPDIR") + "/hosttools" | ||
203 | if "/sh" in shebang: | ||
204 | return hosttools_path + "/sh" | ||
205 | elif "/bash" in shebang: | ||
206 | return hosttools_path + "/bash" | ||
207 | elif "python" in shebang: | ||
208 | return hosttools_path + "/python3" | ||
209 | elif "perl" in shebang: | ||
210 | return hosttools_path + "/perl" | ||
211 | else: | ||
212 | return None | ||
213 | |||
214 | # helper function to get PKGV, useful for recipes such as perf | ||
215 | def get_pkgv(pn): | ||
216 | pkgdestwork = d.getVar("PKGDESTWORK") | ||
217 | recipe_data_fn = pkgdestwork + "/" + pn | ||
218 | pn_data = oe.packagedata.read_pkgdatafile(recipe_data_fn) | ||
219 | if not "PACKAGES" in pn_data: | ||
220 | return d.getVar("PV") | ||
221 | packages = pn_data["PACKAGES"].split() | ||
222 | for pkg in packages: | ||
223 | pkg_fn = pkgdestwork + "/runtime/" + pkg | ||
224 | pkg_data = oe.packagedata.read_pkgdatafile(pkg_fn) | ||
225 | if "PKGV" in pkg_data: | ||
226 | return pkg_data["PKGV"] | ||
227 | |||
228 | # | ||
229 | # traverse PKGD, find executables and run them to get runtime version information and compare it with recipe version information | ||
230 | # | ||
231 | enable_debug = bb.utils.to_boolean(d.getVar("DEBUG_VERSION_MISMATCH_CHECK")) | ||
232 | pkgd = d.getVar("PKGD") | ||
233 | pn = d.getVar("PN") | ||
234 | pv = d.getVar("CHECK_VERSION_PV") | ||
235 | if not pv: | ||
236 | pv = get_pkgv(pn) | ||
237 | qemu_exec = d.getVar("QEMU_EXEC").strip() | ||
238 | executables = [] | ||
239 | possible_versions_all = [] | ||
240 | data_lines = [] | ||
241 | |||
242 | if enable_debug: | ||
243 | debug_directory = d.getVar("TMPDIR") + "/check-version-mismatch" | ||
244 | debug_data_file = debug_directory + "/" + pn | ||
245 | os.makedirs(debug_directory, exist_ok=True) | ||
246 | data_lines.append("pv: %s\n" % pv) | ||
247 | |||
248 | # handle a special case: a pure % means matching all, no point in further checking | ||
249 | if pv == "%": | ||
250 | if enable_debug: | ||
251 | data_lines.append("FINAL RESULT: MATCH (%s matches all, skipped)\n\n" % pv) | ||
252 | with open(debug_data_file, "w") as f: | ||
253 | f.writelines(data_lines) | ||
254 | return | ||
255 | |||
256 | got_quick_match_result = False | ||
257 | # handle python3-xxx recipes quickly | ||
258 | __regex_python_module_version__ = re.compile(r"(?:^|.*:)Version: (?P<version>.*)$") | ||
259 | if "python3-" in pn: | ||
260 | version_check_cmd = "find %s -name 'METADATA' | xargs grep '^Version: '" % pkgd | ||
261 | try: | ||
262 | output = subprocess.check_output(version_check_cmd, shell=True).decode("utf-8") | ||
263 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
264 | data_lines.append("output:\n'''\n%s'''\n" % output) | ||
265 | possible_versions = [] | ||
266 | for line in output.split("\n"): | ||
267 | match = __regex_python_module_version__.match(line) | ||
268 | if match: | ||
269 | possible_versions.append(match.group("version")) | ||
270 | possible_versions = sorted(set(possible_versions)) | ||
271 | data_lines.append("possible versions: %s\n" % possible_versions) | ||
272 | if is_version_mismatch(possible_versions, pv): | ||
273 | data_lines.append("FINAL RESULT: MISMATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
274 | bb.warn("Possible runtime versions %s do not match recipe version %s" % (possible_versions, pv)) | ||
275 | else: | ||
276 | data_lines.append("FINAL RESULT: MATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
277 | got_quick_match_result = True | ||
278 | except: | ||
279 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
280 | data_lines.append("result: RUN_FAILED\n\n") | ||
281 | if got_quick_match_result: | ||
282 | if enable_debug: | ||
283 | with open(debug_data_file, "w") as f: | ||
284 | f.writelines(data_lines) | ||
285 | return | ||
286 | |||
287 | # handle .pc files | ||
288 | version_check_cmd = "find %s -name '*.pc' | xargs grep -i version" % pkgd | ||
289 | try: | ||
290 | output = subprocess.check_output(version_check_cmd, shell=True).decode("utf-8") | ||
291 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
292 | data_lines.append("output:\n'''\n%s'''\n" % output) | ||
293 | possible_versions = get_possible_versions(output) | ||
294 | possible_versions = sorted(set(possible_versions)) | ||
295 | data_lines.append("possible versions: %s\n" % possible_versions) | ||
296 | if is_version_mismatch(possible_versions, pv): | ||
297 | if pn.startswith("lib"): | ||
298 | data_lines.append("FINAL RESULT: MISMATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
299 | bb.warn("Possible runtime versions %s do not match recipe version %s" % (possible_versions, pv)) | ||
300 | got_quick_match_result = True | ||
301 | else: | ||
302 | data_lines.append("result: MISMATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
303 | else: | ||
304 | data_lines.append("FINAL RESULT: MATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
305 | got_quick_match_result = True | ||
306 | except: | ||
307 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
308 | data_lines.append("result: RUN_FAILED\n\n") | ||
309 | if got_quick_match_result: | ||
310 | if enable_debug: | ||
311 | with open(debug_data_file, "w") as f: | ||
312 | f.writelines(data_lines) | ||
313 | return | ||
314 | |||
315 | skipped_directories = [".debug", "ptest", "installed-tests", "tests", "test", "__pycache__", "testcases"] | ||
316 | # avoid checking configuration files, they don't give useful version information and some init scripts | ||
317 | # will kill all processes | ||
318 | skipped_directories.append("etc") | ||
319 | skipped_directories.append("go/src") | ||
320 | pkgd_libdir = pkgd + d.getVar("libdir") | ||
321 | pkgd_base_libdir = pkgd + d.getVar("base_libdir") | ||
322 | extra_exec_libdirs = [] | ||
323 | for root, dirs, files in os.walk(pkgd): | ||
324 | for dname in dirs: | ||
325 | fdir = os.path.join(root, dname) | ||
326 | if os.path.isdir(fdir) and fdir != pkgd_libdir and fdir != pkgd_base_libdir: | ||
327 | if fdir.startswith(pkgd_libdir) or fdir.startswith(pkgd_base_libdir): | ||
328 | for sd in skipped_directories: | ||
329 | if fdir.endswith("/" + sd) or ("/" + sd + "/") in fdir: | ||
330 | break | ||
331 | else: | ||
332 | extra_exec_libdirs.append(fdir) | ||
333 | for fname in files: | ||
334 | fpath = os.path.join(root, fname) | ||
335 | if os.path.isfile(fpath) and os.access(fpath, os.X_OK): | ||
336 | for sd in skipped_directories: | ||
337 | if ("/" + sd + "/") in fpath: | ||
338 | break | ||
339 | else: | ||
340 | if is_shared_library(fpath): | ||
341 | # we don't check shared libraries | ||
342 | continue | ||
343 | else: | ||
344 | executables.append(fpath) | ||
345 | if enable_debug: | ||
346 | data_lines.append("executables: %s\n" % executables) | ||
347 | |||
348 | found_match = False | ||
349 | some_cmd_succeed = False | ||
350 | if not executables: | ||
351 | bb.debug(1, "No executable found for %s" % pn) | ||
352 | data_lines.append("FINAL RESULT: NO_EXECUTABLE_FOUND\n\n") | ||
353 | else: | ||
354 | # first we extend qemu_exec to include library path if needed | ||
355 | if extra_exec_libdirs: | ||
356 | qemu_exec += ":" + ":".join(extra_exec_libdirs) | ||
357 | orig_qemu_exec = qemu_exec | ||
358 | for fexec in executables: | ||
359 | qemu_exec = orig_qemu_exec | ||
360 | for version_option in ["--version", "-V", "-v", "--help"]: | ||
361 | if not is_elf_binary(fexec): | ||
362 | shebang = get_shebang(fexec) | ||
363 | interpreter = get_interpreter_from_shebang(shebang) | ||
364 | if not interpreter: | ||
365 | bb.debug(1, "file %s is not supported to run" % fexec) | ||
366 | elif interpreter.endswith("perl"): | ||
367 | perl5lib_extra = pkgd + d.getVar("libdir") + "/perl5/site_perl" | ||
368 | for p in glob.glob("%s/usr/share/*" % pkgd): | ||
369 | perl5lib_extra += ":%s" % p | ||
370 | qemu_exec += " -E PERL5LIB=%s:$PERL5LIB %s" % (perl5lib_extra, interpreter) | ||
371 | elif interpreter.endswith("python3"): | ||
372 | pythonpath_extra = glob.glob("%s%s/python3*/site-packages" % (pkgd, d.getVar("libdir"))) | ||
373 | if pythonpath_extra: | ||
374 | qemu_exec += " -E PYTHONPATH=%s:$PYTHONPATH %s" % (pythonpath_extra[0], interpreter) | ||
375 | else: | ||
376 | qemu_exec += " %s" % interpreter | ||
377 | # remove the '-E LD_LIBRARY_PATH=xxx' | ||
378 | qemu_exec = re.sub(r"-E\s+LD_LIBRARY_PATH=\S+", "", qemu_exec) | ||
379 | version_check_cmd_full = "%s %s %s" % (qemu_exec, fexec, version_option) | ||
380 | version_check_cmd = version_check_cmd_full | ||
381 | #version_check_cmd = "%s %s" % (os.path.relpath(fexec, pkgd), version_option) | ||
382 | |||
383 | try: | ||
384 | cwd_temp = d.getVar("TMPDIR") + "/check-version-mismatch/cwd-temp/" + pn | ||
385 | os.makedirs(cwd_temp, exist_ok=True) | ||
386 | # avoid pseudo to manage any file we create | ||
387 | sp_env = os.environ.copy() | ||
388 | sp_env["PSEUDO_UNLOAD"] = "1" | ||
389 | output = subprocess.check_output(version_check_cmd_full, | ||
390 | shell=True, | ||
391 | stderr=subprocess.STDOUT, | ||
392 | cwd=cwd_temp, | ||
393 | timeout=10, | ||
394 | env=sp_env).decode("utf-8") | ||
395 | some_cmd_succeed = True | ||
396 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
397 | data_lines.append("output:\n'''\n%s'''\n" % output) | ||
398 | if version_option == "--help": | ||
399 | max_lines = 5 | ||
400 | else: | ||
401 | max_lines = None | ||
402 | possible_versions = get_possible_versions(output, full_cmd=fexec, max_lines=max_lines) | ||
403 | if "." in pv: | ||
404 | possible_versions = [item for item in possible_versions if "." in item or item == "UNKNOWN"] | ||
405 | data_lines.append("possible versions: %s\n" % possible_versions) | ||
406 | if not possible_versions: | ||
407 | data_lines.append("result: NO_RUNTIME_VERSION_FOUND\n\n") | ||
408 | continue | ||
409 | possible_versions_all.extend(possible_versions) | ||
410 | possible_versions_all = sorted(set(possible_versions_all)) | ||
411 | if is_version_mismatch(possible_versions, pv): | ||
412 | data_lines.append("result: MISMATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
413 | else: | ||
414 | found_match = True | ||
415 | data_lines.append("result: MATCH (%s v.s. %s)\n\n" % (possible_versions, pv)) | ||
416 | break | ||
417 | except: | ||
418 | data_lines.append("version_check_cmd: %s\n" % version_check_cmd) | ||
419 | data_lines.append("result: RUN_FAILED\n\n") | ||
420 | finally: | ||
421 | shutil.rmtree(cwd_temp) | ||
422 | if found_match: | ||
423 | break | ||
424 | if executables: | ||
425 | if found_match: | ||
426 | data_lines.append("FINAL RESULT: MATCH (%s v.s. %s)\n" % (possible_versions_all, pv)) | ||
427 | elif len(possible_versions_all) == 0: | ||
428 | if some_cmd_succeed: | ||
429 | bb.debug(1, "No valid runtime version found") | ||
430 | data_lines.append("FINAL RESULT: NO_VALID_RUNTIME_VERSION_FOUND\n") | ||
431 | else: | ||
432 | bb.debug(1, "All version check command failed") | ||
433 | data_lines.append("FINAL RESULT: RUN_FAILED\n") | ||
434 | else: | ||
435 | bb.warn("Possible runtime versions %s do not match recipe version %s" % (possible_versions_all, pv)) | ||
436 | data_lines.append("FINAL RESULT: MISMATCH (%s v.s. %s)\n" % (possible_versions_all, pv)) | ||
437 | |||
438 | if enable_debug: | ||
439 | with open(debug_data_file, "w") as f: | ||
440 | f.writelines(data_lines) | ||
441 | |||
442 | # clean up stale processes | ||
443 | process_name_common_prefix = "%s %s" % (' '.join(qemu_exec.split()[1:]), pkgd) | ||
444 | find_stale_process_cmd = "ps -e -o pid,args | grep -v grep | grep -F '%s'" % process_name_common_prefix | ||
445 | try: | ||
446 | stale_process_output = subprocess.check_output(find_stale_process_cmd, shell=True).decode("utf-8") | ||
447 | stale_process_pids = [] | ||
448 | for line in stale_process_output.split("\n"): | ||
449 | line = line.strip() | ||
450 | if not line: | ||
451 | continue | ||
452 | pid = line.split()[0] | ||
453 | stale_process_pids.append(pid) | ||
454 | for pid in stale_process_pids: | ||
455 | os.kill(int(pid), signal.SIGKILL) | ||
456 | except Exception as e: | ||
457 | bb.debug(1, "No stale process") | ||
458 | } | ||
459 | |||
460 | addtask do_package_check_version_mismatch after do_prepare_recipe_sysroot do_package before do_build | ||
461 | |||
462 | do_build[rdeptask] += "do_package_check_version_mismatch" | ||
463 | do_rootfs[recrdeptask] += "do_package_check_version_mismatch" | ||
464 | |||
465 | SSTATETASKS += "do_package_check_version_mismatch" | ||
466 | do_package_check_version_mismatch[sstate-inputdirs] = "" | ||
467 | do_package_check_version_mismatch[sstate-outputdirs] = "" | ||
468 | python do_package_check_version_mismatch_setscene () { | ||
469 | sstate_setscene(d) | ||
470 | } | ||
471 | addtask do_package_check_version_mismatch_setscene | ||