mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-09-06 18:05:37 +00:00
![Paolo Bonzini](/assets/img/avatar_default.png)
The library directory can change depending on the multilib setup of the host. It would be even better to detect it in configure with the same algorithm that Meson uses, but the important thing to avoid confusing developers is to have identical contents of scripts/meson-buildoptions.sh, independent of the distro and architecture on which it was created. So, for now just give a custom default value to libdir. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
228 lines
6.6 KiB
Python
Executable file
228 lines
6.6 KiB
Python
Executable file
#! /usr/bin/env python3
|
|
|
|
# Generate configure command line options handling code, based on Meson's
|
|
# user build options introspection data
|
|
#
|
|
# Copyright (C) 2021 Red Hat, Inc.
|
|
#
|
|
# Author: Paolo Bonzini <pbonzini@redhat.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2, or (at your option)
|
|
# any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
import json
|
|
import textwrap
|
|
import shlex
|
|
import sys
|
|
|
|
SKIP_OPTIONS = {
|
|
"default_devices",
|
|
"fuzzing_engine",
|
|
"qemu_suffix",
|
|
"smbd",
|
|
}
|
|
|
|
OPTION_NAMES = {
|
|
"b_coverage": "gcov",
|
|
"b_lto": "lto",
|
|
"malloc": "enable-malloc",
|
|
"pkgversion": "with-pkgversion",
|
|
"qemu_firmwarepath": "firmwarepath",
|
|
"trace_backends": "enable-trace-backends",
|
|
"trace_file": "with-trace-file",
|
|
}
|
|
|
|
BUILTIN_OPTIONS = {
|
|
"b_coverage",
|
|
"b_lto",
|
|
"datadir",
|
|
"includedir",
|
|
"libdir",
|
|
"libexecdir",
|
|
"localedir",
|
|
"localstatedir",
|
|
"mandir",
|
|
"strip",
|
|
"sysconfdir",
|
|
}
|
|
|
|
LINE_WIDTH = 76
|
|
|
|
|
|
# Convert the default value of an option to the string used in
|
|
# the help message
|
|
def get_help(opt):
|
|
if opt["name"] == "libdir":
|
|
return 'system default'
|
|
value = opt["value"]
|
|
if isinstance(value, list):
|
|
return ",".join(value)
|
|
if isinstance(value, bool):
|
|
return "enabled" if value else "disabled"
|
|
return str(value)
|
|
|
|
|
|
def wrap(left, text, indent):
|
|
spaces = " " * indent
|
|
if len(left) >= indent:
|
|
yield left
|
|
left = spaces
|
|
else:
|
|
left = (left + spaces)[0:indent]
|
|
yield from textwrap.wrap(
|
|
text, width=LINE_WIDTH, initial_indent=left, subsequent_indent=spaces
|
|
)
|
|
|
|
|
|
def sh_print(line=""):
|
|
print(' printf "%s\\n"', shlex.quote(line))
|
|
|
|
|
|
def help_line(left, opt, indent, long):
|
|
right = f'{opt["description"]}'
|
|
if long:
|
|
value = get_help(opt)
|
|
if value != "auto" and value != "":
|
|
right += f" [{value}]"
|
|
if "choices" in opt and long:
|
|
choices = "/".join(sorted(opt["choices"]))
|
|
right += f" (choices: {choices})"
|
|
for x in wrap(" " + left, right, indent):
|
|
sh_print(x)
|
|
|
|
|
|
# Return whether the option (a dictionary) can be used with
|
|
# arguments. Booleans can never be used with arguments;
|
|
# combos allow an argument only if they accept other values
|
|
# than "auto", "enabled", and "disabled".
|
|
def allow_arg(opt):
|
|
if opt["type"] == "boolean":
|
|
return False
|
|
if opt["type"] != "combo":
|
|
return True
|
|
return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"})
|
|
|
|
|
|
# Return whether the option (a dictionary) can be used without
|
|
# arguments. Booleans can only be used without arguments;
|
|
# combos require an argument if they accept neither "enabled"
|
|
# nor "disabled"
|
|
def require_arg(opt):
|
|
if opt["type"] == "boolean":
|
|
return False
|
|
if opt["type"] != "combo":
|
|
return True
|
|
return not ({"enabled", "disabled"}.intersection(opt["choices"]))
|
|
|
|
|
|
def filter_options(json):
|
|
if ":" in json["name"]:
|
|
return False
|
|
if json["section"] == "user":
|
|
return json["name"] not in SKIP_OPTIONS
|
|
else:
|
|
return json["name"] in BUILTIN_OPTIONS
|
|
|
|
|
|
def load_options(json):
|
|
json = [x for x in json if filter_options(x)]
|
|
return sorted(json, key=lambda x: x["name"])
|
|
|
|
|
|
def cli_option(opt):
|
|
name = opt["name"]
|
|
if name in OPTION_NAMES:
|
|
return OPTION_NAMES[name]
|
|
return name.replace("_", "-")
|
|
|
|
|
|
def cli_help_key(opt):
|
|
key = cli_option(opt)
|
|
if require_arg(opt):
|
|
return key
|
|
if opt["type"] == "boolean" and opt["value"]:
|
|
return f"disable-{key}"
|
|
return f"enable-{key}"
|
|
|
|
|
|
def cli_metavar(opt):
|
|
if opt["type"] == "string":
|
|
return "VALUE"
|
|
if opt["type"] == "array":
|
|
return "CHOICES" if "choices" in opt else "VALUES"
|
|
return "CHOICE"
|
|
|
|
|
|
def print_help(options):
|
|
print("meson_options_help() {")
|
|
for opt in sorted(options, key=cli_help_key):
|
|
key = cli_help_key(opt)
|
|
# The first section includes options that have an arguments,
|
|
# and booleans (i.e., only one of enable/disable makes sense)
|
|
if require_arg(opt):
|
|
metavar = cli_metavar(opt)
|
|
left = f"--{key}={metavar}"
|
|
help_line(left, opt, 27, True)
|
|
elif opt["type"] == "boolean":
|
|
left = f"--{key}"
|
|
help_line(left, opt, 27, False)
|
|
elif allow_arg(opt):
|
|
if opt["type"] == "combo" and "enabled" in opt["choices"]:
|
|
left = f"--{key}[=CHOICE]"
|
|
else:
|
|
left = f"--{key}=CHOICE"
|
|
help_line(left, opt, 27, True)
|
|
|
|
sh_print()
|
|
sh_print("Optional features, enabled with --enable-FEATURE and")
|
|
sh_print("disabled with --disable-FEATURE, default is enabled if available")
|
|
sh_print("(unless built with --without-default-features):")
|
|
sh_print()
|
|
for opt in options:
|
|
key = opt["name"].replace("_", "-")
|
|
if opt["type"] != "boolean" and not allow_arg(opt):
|
|
help_line(key, opt, 18, False)
|
|
print("}")
|
|
|
|
|
|
def print_parse(options):
|
|
print("_meson_option_parse() {")
|
|
print(" case $1 in")
|
|
for opt in options:
|
|
key = cli_option(opt)
|
|
name = opt["name"]
|
|
if require_arg(opt):
|
|
if opt["type"] == "array" and not "choices" in opt:
|
|
print(f' --{key}=*) quote_sh "-D{name}=$(meson_option_build_array $2)" ;;')
|
|
else:
|
|
print(f' --{key}=*) quote_sh "-D{name}=$2" ;;')
|
|
elif opt["type"] == "boolean":
|
|
print(f' --enable-{key}) printf "%s" -D{name}=true ;;')
|
|
print(f' --disable-{key}) printf "%s" -D{name}=false ;;')
|
|
else:
|
|
if opt["type"] == "combo" and "enabled" in opt["choices"]:
|
|
print(f' --enable-{key}) printf "%s" -D{name}=enabled ;;')
|
|
if opt["type"] == "combo" and "disabled" in opt["choices"]:
|
|
print(f' --disable-{key}) printf "%s" -D{name}=disabled ;;')
|
|
if allow_arg(opt):
|
|
print(f' --enable-{key}=*) quote_sh "-D{name}=$2" ;;')
|
|
print(" *) return 1 ;;")
|
|
print(" esac")
|
|
print("}")
|
|
|
|
|
|
options = load_options(json.load(sys.stdin))
|
|
print("# This file is generated by meson-buildoptions.py, do not edit!")
|
|
print_help(options)
|
|
print_parse(options)
|