xref: /qemu/scripts/modinfo-generate.py (revision ebda3036)
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4import os
5import sys
6
7def print_array(name, values):
8    if len(values) == 0:
9        return
10    list = ", ".join(values)
11    print("    .%s = ((const char*[]){ %s, NULL })," % (name, list))
12
13def parse_line(line):
14    kind = ""
15    data = ""
16    get_kind = False
17    get_data = False
18    for item in line.split():
19        if item == "MODINFO_START":
20            get_kind = True
21            continue
22        if item.startswith("MODINFO_END"):
23            get_data = False
24            continue
25        if get_kind:
26            kind = item
27            get_kind = False
28            get_data = True
29            continue
30        if get_data:
31            data += " " + item
32            continue
33    return (kind, data)
34
35def generate(name, lines, enabled):
36    arch = ""
37    objs = []
38    deps = []
39    opts = []
40    for line in lines:
41        if line.find("MODINFO_START") != -1:
42            (kind, data) = parse_line(line)
43            if kind == 'obj':
44                objs.append(data)
45            elif kind == 'dep':
46                deps.append(data)
47            elif kind == 'opts':
48                opts.append(data)
49            elif kind == 'arch':
50                arch = data;
51            elif kind == 'kconfig':
52                # don't add a module which dependency is not enabled
53                # in kconfig
54                if data.strip() not in enabled:
55                    print("    /* module {} isn't enabled in Kconfig. */"
56                          .format(data.strip()))
57                    print("/* },{ */")
58                    return None
59            else:
60                print("unknown:", kind)
61                exit(1)
62
63    print("    .name = \"%s\"," % name)
64    if arch != "":
65        print("    .arch = %s," % arch)
66    print_array("objs", objs)
67    print_array("deps", deps)
68    print_array("opts", opts)
69    print("},{")
70    return {dep.strip('" ') for dep in deps}
71
72def print_pre():
73    print("/* generated by scripts/modinfo-generate.py */")
74    print("#include \"qemu/osdep.h\"")
75    print("#include \"qemu/module.h\"")
76    print("const QemuModinfo qemu_modinfo[] = {{")
77
78def print_post():
79    print("    /* end of list */")
80    print("}};")
81
82def main(args):
83    if len(args) < 3 or args[0] != '--devices':
84        print('Expected: modinfo-generate.py --devices '
85              'config-device.mak [modinfo files]', file=sys.stderr)
86        exit(1)
87
88    # get all devices enabled in kconfig, from *-config-device.mak
89    enabled = set()
90    with open(args[1]) as file:
91        for line in file.readlines():
92            config = line.split('=')
93            if config[1].rstrip() == 'y':
94                enabled.add(config[0][7:]) # remove CONFIG_
95
96    deps = set()
97    modules = set()
98    print_pre()
99    for modinfo in args[2:]:
100        with open(modinfo) as f:
101            lines = f.readlines()
102        print("    /* %s */" % modinfo)
103        (basename, _) = os.path.splitext(modinfo)
104        moddeps = generate(basename, lines, enabled)
105        if moddeps is not None:
106            modules.add(basename)
107            deps.update(moddeps)
108    print_post()
109
110    error = False
111    for dep in deps.difference(modules):
112        print("Dependency {} cannot be satisfied".format(dep),
113              file=sys.stderr)
114        error = True
115
116    if error:
117        exit(1)
118
119if __name__ == "__main__":
120    main(sys.argv[1:])
121