Re: [PATCH v3 03/24] modules: generate modinfo.c

2021-06-22 Thread Jose R. Ziviani
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 
> ---
>  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 ..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  */
>  #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 

Re: [PATCH v3 03/24] modules: generate modinfo.c

2021-06-22 Thread Jose R. Ziviani
Hello,

Just a small change.

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 
> ---
>  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 ..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 */")

generated by scripts/modinfo-generate.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()
> +
> +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  */
>  #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