vppapigen: make json in parallel
[vpp.git] / src / tools / vppapigen / generate_json.py
1 #!/usr/bin/env python3
2 #  Copyright (c) 2019. Vinci Consulting Corp. All Rights Reserved.
3 #
4 #  Licensed under the Apache License, Version 2.0 (the "License");
5 #  you may not use this file except in compliance with the License.
6 #  You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #  Unless required by applicable law or agreed to in writing, software
11 #  distributed under the License is distributed on an "AS IS" BASIS,
12 #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 #  See the License for the specific language governing permissions and
14 #  limitations under the License.
15
16 import argparse
17 import pathlib
18 import subprocess
19 import vppapigen
20 import os
21 from multiprocessing import Pool
22
23 BASE_DIR = (
24     subprocess.check_output("git rev-parse --show-toplevel", shell=True)
25     .strip()
26     .decode()
27 )
28
29 src_dir_depth = 3
30 output_path = pathlib.Path(
31     "%s/build-root/install-vpp-native/vpp/share/vpp/api/" % BASE_DIR
32 )
33 output_path_debug = pathlib.Path(
34     "%s/build-root/install-vpp_debug-native/vpp/share/vpp/api/" % BASE_DIR
35 )
36
37 output_dir_map = {
38     "plugins": "plugins",
39     "vlibmemory": "core",
40     "vnet": "core",
41     "vlib": "core",
42     "vpp": "core",
43 }
44
45
46 def api_search_globs(src_dir):
47     globs = []
48     for g in output_dir_map:
49         globs.extend(list(src_dir.glob("%s/**/*.api" % g)))
50     return globs
51
52
53 def api_files(src_dir):
54     print("Searching '%s' for .api files." % src_dir.as_posix())
55     return [x for x in api_search_globs(src_dir)]
56
57
58 def get_n_parallel(n_parallel):
59     if n_parallel == 0:
60         n_parallel = os.environ.get("MAKE_PARALLEL_JOBS", os.cpu_count())
61         try:
62             n_parallel = int(n_parallel)
63         except ValueError:
64             return os.cpu_count()
65     return n_parallel or os.cpu_count()
66
67
68 def main():
69     cliparser = argparse.ArgumentParser(description="VPP API JSON definition generator")
70     cliparser.add_argument("--srcdir", action="store", default="%s/src" % BASE_DIR),
71     cliparser.add_argument("--output", action="store", help="directory to store files"),
72     cliparser.add_argument(
73         "--parallel", type=int, default=0, help="Number of parallel processes"
74     ),
75     cliparser.add_argument(
76         "--debug-target",
77         action="store_true",
78         default=False,
79         help="'True' if -debug target",
80     ),
81
82     args = cliparser.parse_args()
83
84     src_dir = pathlib.Path(args.srcdir)
85     output_target = output_path_debug if args.debug_target else output_path
86
87     if args.output:
88         output_dir = pathlib.Path(args.output)
89     else:
90         output_dir = pathlib.Path(output_target)
91
92     for d in output_dir_map.values():
93         output_dir.joinpath(d).mkdir(exist_ok=True, parents=True)
94
95     for f in output_dir.glob("**/*.api.json"):
96         f.unlink()
97
98     with Pool(get_n_parallel(args.parallel)) as p:
99         p.map(
100             vppapigen.run_kw_vppapigen,
101             [
102                 {
103                     "output": "%s/%s/%s.json"
104                     % (
105                         output_path,
106                         output_dir_map[
107                             f.as_posix().split("/")[
108                                 src_dir_depth + BASE_DIR.count("/") - 1
109                             ]
110                         ],
111                         f.name,
112                     ),
113                     "input_file": f.as_posix(),
114                     "includedir": [src_dir.as_posix()],
115                     "output_module": "JSON",
116                 }
117                 for f in api_files(src_dir)
118             ],
119         )
120
121     print("json files written to: %s/." % output_dir)
122
123
124 if __name__ == "__main__":
125     main()