292
|
1 #!/usr/bin/env python
|
104
|
2
|
287
|
3 import sys
|
331
|
4 import os
|
287
|
5 import argparse
|
|
6 import logging
|
331
|
7 import yaml
|
287
|
8
|
329
|
9 from ppci.buildtasks import Compile
|
|
10 from ppci.tasks import TaskRunner
|
331
|
11 from ppci.report import RstFormatter
|
205
|
12 import outstream
|
323
|
13 from target.target_list import target_list
|
331
|
14 import ppci
|
281
|
15
|
289
|
16
|
253
|
17 def logLevel(s):
|
312
|
18 """ Converts a string to a valid logging level """
|
253
|
19 numeric_level = getattr(logging, s.upper(), None)
|
|
20 if not isinstance(numeric_level, int):
|
|
21 raise ValueError('Invalid log level: {}'.format(s))
|
|
22 return numeric_level
|
105
|
23
|
289
|
24
|
323
|
25 targets = {t.name: t for t in target_list}
|
292
|
26 targetnames = list(targets.keys())
|
290
|
27
|
331
|
28 def make_parser():
|
|
29 parser = argparse.ArgumentParser(description='lcfos Compiler')
|
|
30
|
|
31 parser.add_argument('--log', help='Log level (INFO,DEBUG,[WARN])',
|
|
32 type=logLevel, default='WARN')
|
332
|
33 parser.add_argument('--display-build-steps', action='store_true')
|
331
|
34 sub_parsers = parser.add_subparsers(title='commands',
|
|
35 description='possible commands', dest='command')
|
|
36 recipe_parser = sub_parsers.add_parser('recipe', help="Bake recipe")
|
|
37 recipe_parser.add_argument('recipe_file', help='recipe file')
|
|
38
|
|
39 compile_parser = sub_parsers.add_parser('compile', help="compile source")
|
|
40 compile_parser.add_argument('source', type=argparse.FileType('r'),
|
|
41 help='the source file to build', nargs="+")
|
|
42 compile_parser.add_argument('-i', '--imp', type=argparse.FileType('r'),
|
|
43 help='Possible import module', action='append', default=[])
|
|
44 compile_parser.add_argument('--target', help="Backend selection",
|
|
45 choices=targetnames, required=True)
|
|
46 compile_parser.add_argument('-o', '--output', help='Output file',
|
|
47 metavar='filename')
|
|
48 compile_parser.add_argument('--report',
|
|
49 help='Specify a file to write the compile report to',
|
|
50 type=argparse.FileType('w'))
|
|
51 return parser
|
|
52
|
287
|
53
|
331
|
54 class RecipeLoader:
|
|
55 def load_file(self, recipe_file, runner):
|
|
56 """ Loads a recipe dictionary into a task runner """
|
|
57 self.recipe_dir = os.path.abspath(os.path.dirname(recipe_file))
|
|
58 with open(recipe_file, 'r') as f:
|
|
59 recipe = yaml.load(f)
|
|
60 self.load_dict(recipe, runner)
|
|
61
|
|
62 def relpath(self, filename):
|
|
63 return os.path.join(self.recipe_dir, filename)
|
|
64
|
|
65 def openfile(self, filename):
|
|
66 return open(self.relpath(filename), 'r')
|
|
67
|
|
68 def load_dict(self, recipe, runner):
|
|
69 for command, value in recipe.items():
|
|
70 if command == 'compile':
|
|
71 sources = [self.openfile(s) for s in value['sources']]
|
|
72 includes = [self.openfile(i) for i in value['includes']]
|
|
73 target = targets[value['machine']]
|
|
74 output = outstream.TextOutputStream()
|
|
75 runner.add_task(Compile(sources, includes, target, output))
|
|
76 elif command == 'link':
|
|
77 self.load_dict(value['inputs'], runner)
|
|
78 #runner.add_task(Link())
|
|
79 elif command == 'assemble':
|
|
80 pass
|
|
81 elif command == 'apps':
|
|
82 for a in value:
|
|
83 self.load_dict(a, runner)
|
|
84 else:
|
|
85 raise NotImplementedError(command)
|
104
|
86
|
288
|
87
|
249
|
88 def main(args):
|
315
|
89 # Configure some logging:
|
|
90 logging.getLogger().setLevel(logging.DEBUG)
|
|
91 ch = logging.StreamHandler()
|
331
|
92 ch.setFormatter(logging.Formatter(ppci.logformat))
|
315
|
93 ch.setLevel(args.log)
|
|
94 logging.getLogger().addHandler(ch)
|
329
|
95
|
331
|
96 runner = TaskRunner()
|
|
97 if args.command == 'compile':
|
|
98 tg = targets[args.target]
|
|
99 outs = outstream.TextOutputStream()
|
|
100 runner.add_task(Compile(args.source, args.imp, tg, outs))
|
|
101 elif args.command == 'recipe':
|
|
102 recipe_loader = RecipeLoader()
|
|
103 recipe_loader.load_file(args.recipe_file, runner)
|
|
104 else:
|
|
105 raise NotImplementedError('Invalid option')
|
105
|
106
|
332
|
107 if args.display_build_steps:
|
|
108 runner.display()
|
|
109 res = 0
|
|
110 else:
|
|
111 res = runner.run_tasks()
|
104
|
112
|
315
|
113 logging.getLogger().removeHandler(ch)
|
331
|
114 return res
|
246
|
115
|
288
|
116
|
207
|
117 if __name__ == '__main__':
|
331
|
118 parser = make_parser()
|
213
|
119 arguments = parser.parse_args()
|
331
|
120 if not arguments.command:
|
|
121 parser.print_usage()
|
|
122 sys.exit(1)
|
276
|
123 sys.exit(main(arguments))
|