Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # Prepare the build system within the extensible SDK |
| 4 | |
| 5 | import sys |
| 6 | import os |
| 7 | import subprocess |
| 8 | |
| 9 | def exec_watch(cmd, **options): |
| 10 | """Run program with stdout shown on sys.stdout""" |
| 11 | if isinstance(cmd, basestring) and not "shell" in options: |
| 12 | options["shell"] = True |
| 13 | |
| 14 | process = subprocess.Popen( |
| 15 | cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **options |
| 16 | ) |
| 17 | |
| 18 | buf = '' |
| 19 | while True: |
| 20 | out = process.stdout.read(1) |
| 21 | if out: |
| 22 | sys.stdout.write(out) |
| 23 | sys.stdout.flush() |
| 24 | buf += out |
| 25 | elif out == '' and process.poll() != None: |
| 26 | break |
| 27 | |
| 28 | return process.returncode, buf |
| 29 | |
| 30 | def check_unexpected(lines, recipes): |
| 31 | """Check for unexpected output lines from dry run""" |
| 32 | unexpected = [] |
| 33 | for line in lines.splitlines(): |
| 34 | if 'Running task' in line: |
| 35 | for recipe in recipes: |
| 36 | if recipe in line: |
| 37 | break |
| 38 | else: |
| 39 | line = line.split('Running', 1)[-1] |
| 40 | if 'do_rm_work' not in line: |
| 41 | unexpected.append(line.rstrip()) |
| 42 | elif 'Running setscene' in line: |
| 43 | unexpected.append(line.rstrip()) |
| 44 | return unexpected |
| 45 | |
| 46 | def main(): |
| 47 | if len(sys.argv) < 2: |
| 48 | sdk_targets = [] |
| 49 | else: |
| 50 | sdk_targets = ' '.join(sys.argv[1:]).split() |
| 51 | if not sdk_targets: |
| 52 | # Just do a parse so the cache is primed |
| 53 | ret, _ = exec_watch('bitbake -p') |
| 54 | return ret |
| 55 | |
| 56 | print('Preparing SDK for %s...' % ', '.join(sdk_targets)) |
| 57 | |
| 58 | ret, out = exec_watch('bitbake %s --setscene-only' % ' '.join(sdk_targets)) |
| 59 | if ret: |
| 60 | return ret |
| 61 | |
| 62 | targetlist = [] |
| 63 | for target in sdk_targets: |
| 64 | if ':' in target: |
| 65 | target = target.split(':')[0] |
| 66 | if not target in targetlist: |
| 67 | targetlist.append(target) |
| 68 | |
| 69 | recipes = [] |
| 70 | for target in targetlist: |
| 71 | try: |
| 72 | out = subprocess.check_output(('bitbake -e %s' % target).split(), stderr=subprocess.STDOUT) |
| 73 | for line in out.splitlines(): |
| 74 | if line.startswith('FILE='): |
| 75 | splitval = line.rstrip().split('=') |
| 76 | if len(splitval) > 1: |
| 77 | recipes.append(splitval[1].strip('"')) |
| 78 | break |
| 79 | except subprocess.CalledProcessError as e: |
| 80 | print('ERROR: Failed to get recipe for target %s:\n%s' % (target, e.output)) |
| 81 | return 1 |
| 82 | |
| 83 | try: |
| 84 | out = subprocess.check_output('bitbake %s -n' % ' '.join(sdk_targets), stderr=subprocess.STDOUT, shell=True) |
| 85 | unexpected = check_unexpected(out, recipes) |
| 86 | except subprocess.CalledProcessError as e: |
| 87 | print('ERROR: Failed to execute dry-run:\n%s' % e.output) |
| 88 | return 1 |
| 89 | |
| 90 | if unexpected: |
| 91 | print('ERROR: Unexpected tasks or setscene left over to be executed:') |
| 92 | for line in unexpected: |
| 93 | print(' ' + line) |
| 94 | return 1 |
| 95 | |
| 96 | if __name__ == "__main__": |
| 97 | try: |
| 98 | ret = main() |
| 99 | except Exception: |
| 100 | ret = 1 |
| 101 | import traceback |
| 102 | traceback.print_exc() |
| 103 | sys.exit(ret) |