On Fri, Jun 18, 2021 at 06:53:32AM +0200, Gerd Hoffmann wrote: > Add script to generate C source with a small > database containing the module meta-data. > > Signed-off-by: Gerd Hoffmann <[email protected]> > --- > scripts/modinfo-generate.py | 84 +++++++++++++++++++++++++++++++++++++ > include/qemu/module.h | 17 ++++++++ > softmmu/vl.c | 4 ++ > util/module.c | 11 +++++ > meson.build | 13 +++++- > 5 files changed, 128 insertions(+), 1 deletion(-) > create mode 100755 scripts/modinfo-generate.py > > diff --git a/scripts/modinfo-generate.py b/scripts/modinfo-generate.py > new file mode 100755 > index 000000000000..2b925432655a > --- /dev/null > +++ b/scripts/modinfo-generate.py > @@ -0,0 +1,84 @@ > +#!/usr/bin/env python3 > +# -*- coding: utf-8 -*- > + > +import os > +import sys > + > +def print_array(name, values): > + if len(values) == 0: > + return > + list = ", ".join(values) > + print(" .%s = ((const char*[]){ %s, NULL })," % (name, list)) > + > +def parse_line(line): > + kind = "" > + data = "" > + get_kind = False > + get_data = False > + for item in line.split(): > + if item == "MODINFO_START": > + get_kind = True > + continue > + if item.startswith("MODINFO_END"): > + get_data = False > + continue > + if get_kind: > + kind = item > + get_kind = False > + get_data = True > + continue > + if get_data: > + data += " " + item > + continue > + return (kind, data) > + > +def generate(name, lines): > + arch = "" > + objs = [] > + deps = [] > + opts = [] > + for line in lines: > + if line.find("MODINFO_START") != -1: > + (kind, data) = parse_line(line) > + if kind == 'obj': > + objs.append(data) > + elif kind == 'dep': > + deps.append(data) > + elif kind == 'opts': > + opts.append(data) > + elif kind == 'arch': > + arch = data; > + else: > + print("unknown:", kind) > + exit(1) > + > + print(" .name = \"%s\"," % name) > + if arch != "": > + print(" .arch = %s," % arch) > + print_array("objs", objs) > + print_array("deps", deps) > + print_array("opts", opts) > + print("},{"); > + > +def print_pre(): > + print("/* generated by scripts/modinfo.py */") > + print("#include \"qemu/osdep.h\"") > + print("#include \"qemu/module.h\"") > + print("const QemuModinfo qemu_modinfo[] = {{") > + > +def print_post(): > + print(" /* end of list */") > + print("}};") > + > +def main(args): > + print_pre() > + for modinfo in args: > + with open(modinfo) as f: > + lines = f.readlines() > + print(" /* %s */" % modinfo) > + (basename, ext) = os.path.splitext(modinfo) > + generate(basename, lines) > + print_post()
I attached a patch in this message to check if a dependency can be satisfied.
It will detect the following case:
(in any module)
module_dep("blabla");
[2/5] Generating modinfo.c with a custom command (wrapped by meson to capture
output)
FAILED: modinfo.c
/usr/bin/meson --internal exe --capture modinfo.c -- /home/...
Dependency blabla cannot be satisfied
/* generated by scripts/modinfo.py */
#include "qemu/osdep.h"
#include "qemu/module.h"
const QemuModinfo qemu_modinfo[] = {{
/* ui-curses.modinfo */
.name = "ui-curses",
...
},{
/* accel-tcg-x86_64.modinfo */
.name = "accel-tcg-x86_64",
.arch = "x86_64",
.objs = ((const char*[]){ ("tcg" "-" "accel" "-ops"), NULL }),
.deps = ((const char*[]){ "blabla", NULL }),
},{
/* end of list */
}};
ninja: build stopped: subcommand failed.
make: *** [Makefile:154: run-ninja] Error 1
It can help developers to know early they have a typo somewhere.
You can add this code if you like.
> +
> +if __name__ == "__main__":
> + main(sys.argv[1:])
> diff --git a/include/qemu/module.h b/include/qemu/module.h
> index 81ef086da023..a98748d501d3 100644
> --- a/include/qemu/module.h
> +++ b/include/qemu/module.h
> @@ -98,4 +98,21 @@ void module_load_qom_all(void);
> /* module registers QemuOpts <name> */
> #define module_opts(name) modinfo(opts, name)
>
> +/*
> + * module info database
> + *
> + * scripts/modinfo-generate.c will build this using the data collected
> + * by scripts/modinfo-collect.py
> + */
> +typedef struct QemuModinfo QemuModinfo;
> +struct QemuModinfo {
> + const char *name;
> + const char *arch;
> + const char **objs;
> + const char **deps;
> + const char **opts;
> +};
> +extern const QemuModinfo qemu_modinfo[];
> +void module_init_info(const QemuModinfo *info);
> +
> #endif
> diff --git a/softmmu/vl.c b/softmmu/vl.c
> index 326c1e908008..a4857ec43ff3 100644
> --- a/softmmu/vl.c
> +++ b/softmmu/vl.c
> @@ -2740,6 +2740,10 @@ void qemu_init(int argc, char **argv, char **envp)
> error_init(argv[0]);
> qemu_init_exec_dir(argv[0]);
>
> +#ifdef CONFIG_MODULES
> + module_init_info(qemu_modinfo);
> +#endif
> +
> qemu_init_subsystems();
>
> /* first pass of option parsing */
> diff --git a/util/module.c b/util/module.c
> index eee8ff2de136..8d3e8275b9f7 100644
> --- a/util/module.c
> +++ b/util/module.c
> @@ -110,6 +110,17 @@ void module_call_init(module_init_type type)
> }
>
> #ifdef CONFIG_MODULES
> +
> +static const QemuModinfo module_info_stub[] = { {
> + /* end of list */
> +} };
> +static const QemuModinfo *module_info = module_info_stub;
> +
> +void module_init_info(const QemuModinfo *info)
> +{
> + module_info = info;
> +}
> +
> static int module_load_file(const char *fname, bool mayfail, bool
> export_symbols)
> {
> GModule *g_module;
> diff --git a/meson.build b/meson.build
> index bb99619257d5..9cf50a50d39a 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2022,6 +2022,7 @@ subdir('tests/qtest/fuzz')
> ########################
>
> modinfo_collect = find_program('scripts/modinfo-collect.py')
> +modinfo_generate = find_program('scripts/modinfo-generate.py')
> modinfo_files = []
>
> block_mods = []
> @@ -2042,7 +2043,6 @@ foreach d, list : modules
> output: d + '-' + m + '.modinfo',
> input: module_ss.sources(),
> capture: true,
> - build_by_default: true, # to be
> removed when added to a target
> command: [modinfo_collect, '@INPUT@'])
> endif
> else
> @@ -2055,6 +2055,17 @@ foreach d, list : modules
> endforeach
> endforeach
>
> +if enable_modules
> + modinfo_src = custom_target('modinfo.c',
> + output: 'modinfo.c',
> + input: modinfo_files,
> + command: [modinfo_generate, '@INPUT@'],
> + capture: true)
> + modinfo_lib = static_library('modinfo', modinfo_src)
> + modinfo_dep = declare_dependency(link_whole: modinfo_lib)
> + softmmu_ss.add(modinfo_dep)
> +endif
> +
> nm = find_program('nm')
> undefsym = find_program('scripts/undefsym.py')
> block_syms = custom_target('block.syms', output: 'block.syms',
> --
> 2.31.1
>
>
From 0e6866bcae2d6576e7dbc08d8bbd2837f655d5a3 Mon Sep 17 00:00:00 2001 From: "Jose R. Ziviani" <[email protected]> Date: Tue, 22 Jun 2021 17:37:42 -0300 Subject: [PATCH] modules: check if all dependencies can be satisfied Verifies if all dependencies are correctly listed in the modinfo.c too and stop the builds if they're not. Signed-off-by: Jose R. Ziviani <[email protected]> --- scripts/modinfo-generate.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/modinfo-generate.py b/scripts/modinfo-generate.py index 2b92543265..a36ddb77dd 100755 --- a/scripts/modinfo-generate.py +++ b/scripts/modinfo-generate.py @@ -59,6 +59,7 @@ def generate(name, lines): print_array("deps", deps) print_array("opts", opts) print("},{"); + return deps def print_pre(): print("/* generated by scripts/modinfo.py */") @@ -71,14 +72,26 @@ def print_post(): print("}};") def main(args): + deps = {} print_pre() for modinfo in args: with open(modinfo) as f: lines = f.readlines() print(" /* %s */" % modinfo) (basename, ext) = os.path.splitext(modinfo) - generate(basename, lines) + deps[basename] = generate(basename, lines) print_post() + flattened_deps = {flat.strip('" ') for dep in deps.values() for flat in dep} + error = False + for dep in flattened_deps: + if dep not in deps.keys(): + print("Dependency {} cannot be satisfied".format(dep), + file=sys.stderr) + error = True + + if error: + exit(1) + if __name__ == "__main__": main(sys.argv[1:]) -- 2.32.0
signature.asc
Description: Digital signature
