blob: e2236604436ca68a2cde0da9722f377adfce0f19 [file] [log] [blame]
Zack Williams9a42f872019-02-15 17:56:04 -07001#!/usr/bin/env python
2
Matteo Scandolod2044a42017-08-07 16:08:28 -07003# Copyright 2017-present Open Networking Foundation
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Zack Williams9a42f872019-02-15 17:56:04 -070017from __future__ import absolute_import, print_function
Matteo Scandolod2044a42017-08-07 16:08:28 -070018
Matteo Scandolo67654fa2017-06-09 09:33:17 -070019import argparse
Zack Williams9a42f872019-02-15 17:56:04 -070020import os
21from functools import reduce
22
23from six.moves import range
24
25from .generator import XOSProcessor, XOSProcessorArgs
26from .version import __version__
Matteo Scandolo67654fa2017-06-09 09:33:17 -070027
Zack Williams045b63d2019-01-22 16:30:57 -070028parse = argparse.ArgumentParser(description="XOS Generative Toolchain")
29parse.add_argument(
30 "--rev",
31 dest="rev",
32 action="store_true",
33 default=XOSProcessorArgs.default_rev,
34 help="Convert proto to xproto",
35)
36parse.add_argument(
37 "--output",
38 dest="output",
39 action="store",
40 default=XOSProcessorArgs.default_output,
41 help="Destination dir",
42)
43parse.add_argument(
44 "--attic",
45 dest="attic",
46 action="store",
47 default=XOSProcessorArgs.default_attic,
48 help="The location at which static files are stored",
49)
50parse.add_argument(
51 "--kvpairs",
52 dest="kv",
53 action="store",
54 default=XOSProcessorArgs.default_kvpairs,
55 help="Key value pairs to make available to the target",
56)
57parse.add_argument(
58 "--write-to-file",
59 dest="write_to_file",
60 choices=["single", "model", "target"],
61 action="store",
62 default=XOSProcessorArgs.default_write_to_file,
63 help="Single output file (single) or output file per model (model) or let target decide (target)",
64)
65parse.add_argument("--version", action="version", version=__version__)
66parse.add_argument(
67 "-v",
68 "--verbosity",
69 action="count",
70 default=XOSProcessorArgs.default_verbosity,
71 help="increase output verbosity",
72)
73parse.add_argument(
74 "--include-models",
75 dest="include_models",
76 action="append",
77 default=XOSProcessorArgs.default_include_models,
78 help="list of models to include",
79)
80parse.add_argument(
81 "--include-apps",
82 dest="include_apps",
83 action="append",
84 default=XOSProcessorArgs.default_include_apps,
85 help="list of models to include",
86)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070087
88group = parse.add_mutually_exclusive_group()
Zack Williams045b63d2019-01-22 16:30:57 -070089group.add_argument(
90 "--dest-file",
91 dest="dest_file",
92 action="store",
93 default=XOSProcessorArgs.default_dest_file,
94 help="Output file name (if write-to-file is set to single)",
95)
96group.add_argument(
97 "--dest-extension",
98 dest="dest_extension",
99 action="store",
100 default=XOSProcessorArgs.default_dest_extension,
101 help="Output file extension (if write-to-file is set to single)",
102)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700103
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800104group = parse.add_mutually_exclusive_group(required=True)
Zack Williams045b63d2019-01-22 16:30:57 -0700105group.add_argument(
106 "--target",
107 dest="target",
108 action="store",
109 default=XOSProcessorArgs.default_target,
110 help="Output format, corresponding to <output>.yaml file",
111)
112group.add_argument(
113 "--checkers",
114 dest="checkers",
115 action="store",
116 default=XOSProcessorArgs.default_checkers,
117 help="Comma-separated list of static checkers",
118)
Scott Baker08d10402019-04-08 16:19:59 -0700119group.add_argument(
120 "--lint",
121 dest="lint",
122 action="store_true",
123 default=XOSProcessorArgs.default_lint,
124 help="Parse the xproto but don't execute any xtargets",
125)
126
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800127
Zack Williams045b63d2019-01-22 16:30:57 -0700128parse.add_argument(
129 "files",
130 metavar="<input file>",
131 nargs="+",
132 action="store",
133 help="xproto files to compile",
134)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700135
Scott Baker7ae3a8f2019-03-05 16:24:14 -0800136parse.add_argument(
137 "--strict-validation",
138 dest="strict_validation",
139 action="store_true",
140 default=XOSProcessorArgs.default_strict_validation,
141 help="Exit if validation fails",
142)
143
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800144CHECK = 1
145GEN = 2
Scott Baker08d10402019-04-08 16:19:59 -0700146LINT = 3
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800147
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700148
Zack Williams045b63d2019-01-22 16:30:57 -0700149class XosGen:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700150 @staticmethod
151 def init(args=None):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700152 if not args:
153 args = parse.parse_args()
154
155 args.quiet = False
156
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800157 if args.target:
158 op = GEN
Zack Williams045b63d2019-01-22 16:30:57 -0700159 subdir = "/targets/"
Scott Baker08d10402019-04-08 16:19:59 -0700160 operators = [args.target]
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800161 elif args.checkers:
162 op = CHECK
Zack Williams045b63d2019-01-22 16:30:57 -0700163 subdir = "/checkers/"
Scott Baker08d10402019-04-08 16:19:59 -0700164 operators = args.checkers
165 elif args.lint:
166 op = LINT
167 subdir = None
168 operators = []
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800169 else:
Scott Baker08d10402019-04-08 16:19:59 -0700170 parse.error("At least one of --target, --checkers, or --lint is required")
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700171
Zack Williams9a42f872019-02-15 17:56:04 -0700172 for i in range(len(operators)):
Zack Williams045b63d2019-01-22 16:30:57 -0700173 if "/" not in operators[i]:
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800174 # if the target is not a path, it refer to a library included one
Zack Williams045b63d2019-01-22 16:30:57 -0700175 operators[i] = os.path.abspath(
176 os.path.dirname(os.path.realpath(__file__)) + subdir + operators[i]
177 )
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700178
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800179 if not os.path.isabs(operators[i]):
Zack Williams045b63d2019-01-22 16:30:57 -0700180 operators[i] = os.path.abspath(os.getcwd() + "/" + operators[i])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700181
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800182 if op == GEN:
183 # convert output to absolute path
184 if args.output is not None and not os.path.isabs(args.output):
Zack Williams045b63d2019-01-22 16:30:57 -0700185 args.output = os.path.abspath(os.getcwd() + "/" + args.output)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700186
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800187 operator = operators[0]
Zack Williams045b63d2019-01-22 16:30:57 -0700188
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800189 # check if there's a line that starts with +++ in the target
190 # if so, then the output file names are left to the target to decide
191 # also, if dest-file or dest-extension are supplied, then an error is generated.
Zack Williams045b63d2019-01-22 16:30:57 -0700192 plusplusplus = reduce(
193 lambda acc, line: True if line.startswith("+++") else acc,
194 open(operator).read().splitlines(),
195 False,
196 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800197
Zack Williams045b63d2019-01-22 16:30:57 -0700198 if plusplusplus and args.write_to_file != "target":
199 parse.error(
200 '%s chooses the names of the files that it generates, you must set --write-to-file to "target"'
201 % operator
202 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800203
Zack Williams045b63d2019-01-22 16:30:57 -0700204 if args.write_to_file != "single" and (args.dest_file):
205 parse.error(
206 '--dest-file requires --write-to-file to be set to "single"'
207 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800208
Zack Williams045b63d2019-01-22 16:30:57 -0700209 if args.write_to_file != "model" and (args.dest_extension):
210 parse.error(
211 '--dest-extension requires --write-to-file to be set to "model"'
212 )
213
Scott Baker08d10402019-04-08 16:19:59 -0700214 elif op == CHECK:
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800215 if args.write_to_file or args.dest_extension:
Zack Williams045b63d2019-01-22 16:30:57 -0700216 parse.error("Checkers cannot write to files")
Scott Baker08d10402019-04-08 16:19:59 -0700217 elif op == LINT:
218 # no outputs, so nothing to check
219 pass
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700220
221 inputs = []
222
223 for fname in args.files:
224 if not os.path.isabs(fname):
Zack Williams045b63d2019-01-22 16:30:57 -0700225 inputs.append(os.path.abspath(os.getcwd() + "/" + fname))
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700226 else:
227 inputs.append(fname)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800228
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700229 args.files = inputs
230
Zack Williams045b63d2019-01-22 16:30:57 -0700231 if op == GEN:
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800232 generated = XOSProcessor.process(args, operators[0])
233 if not args.output and not args.write_to_file:
Zack Williams045b63d2019-01-22 16:30:57 -0700234 print(generated)
235 elif op == CHECK:
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800236 for o in operators:
237 verdict_str = XOSProcessor.process(args, o)
Zack Williams045b63d2019-01-22 16:30:57 -0700238 vlst = verdict_str.split("\n")
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700239
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800240 try:
241 verdict = next(v for v in vlst if v.strip())
Zack Williams045b63d2019-01-22 16:30:57 -0700242 status_code, status_string = verdict.split(" ", 1)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800243 status_code = int(status_code)
Zack Williams045b63d2019-01-22 16:30:57 -0700244 except BaseException:
245 print("Checker %s returned mangled output" % o)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800246 exit(1)
247
248 if status_code != 200:
Zack Williams045b63d2019-01-22 16:30:57 -0700249 print("%s: %s - %s" % (o, status_code, status_string))
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800250 exit(1)
251 else:
Zack Williams045b63d2019-01-22 16:30:57 -0700252 print("%s: OK" % o)
Scott Baker08d10402019-04-08 16:19:59 -0700253 elif op == LINT:
254 XOSProcessor.process(args, None)