]> git.proxmox.com Git - mirror_qemu.git/blob - scripts/meson-buildoptions.py
9p: darwin: *xattr_nofollow implementations
[mirror_qemu.git] / scripts / meson-buildoptions.py
1 #! /usr/bin/env python3
2
3 # Generate configure command line options handling code, based on Meson's
4 # user build options introspection data
5 #
6 # Copyright (C) 2021 Red Hat, Inc.
7 #
8 # Author: Paolo Bonzini <pbonzini@redhat.com>
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2, or (at your option)
13 # any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, see <https://www.gnu.org/licenses/>.
22
23 import json
24 import textwrap
25 import shlex
26 import sys
27
28 SKIP_OPTIONS = {
29 "audio_drv_list",
30 "default_devices",
31 "docdir",
32 "fuzzing_engine",
33 "iasl",
34 "qemu_firmwarepath",
35 "qemu_suffix",
36 "smbd",
37 "sphinx_build",
38 "trace_file",
39 }
40
41 BUILTIN_OPTIONS = {
42 "strip",
43 }
44
45 LINE_WIDTH = 76
46
47
48 # Convert the default value of an option to the string used in
49 # the help message
50 def value_to_help(value):
51 if isinstance(value, list):
52 return ",".join(value)
53 if isinstance(value, bool):
54 return "enabled" if value else "disabled"
55 return str(value)
56
57
58 def wrap(left, text, indent):
59 spaces = " " * indent
60 if len(left) >= indent:
61 yield left
62 left = spaces
63 else:
64 left = (left + spaces)[0:indent]
65 yield from textwrap.wrap(
66 text, width=LINE_WIDTH, initial_indent=left, subsequent_indent=spaces
67 )
68
69
70 def sh_print(line=""):
71 print(' printf "%s\\n"', shlex.quote(line))
72
73
74 def help_line(left, opt, indent, long):
75 right = f'{opt["description"]}'
76 if long:
77 value = value_to_help(opt["value"])
78 if value != "auto":
79 right += f" [{value}]"
80 if "choices" in opt and long:
81 choices = "/".join(sorted(opt["choices"]))
82 right += f" (choices: {choices})"
83 for x in wrap(" " + left, right, indent):
84 sh_print(x)
85
86
87 # Return whether the option (a dictionary) can be used with
88 # arguments. Booleans can never be used with arguments;
89 # combos allow an argument only if they accept other values
90 # than "auto", "enabled", and "disabled".
91 def allow_arg(opt):
92 if opt["type"] == "boolean":
93 return False
94 if opt["type"] != "combo":
95 return True
96 return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"})
97
98
99 def filter_options(json):
100 if ":" in json["name"]:
101 return False
102 if json["section"] == "user":
103 return json["name"] not in SKIP_OPTIONS
104 else:
105 return json["name"] in BUILTIN_OPTIONS
106
107
108 def load_options(json):
109 json = [x for x in json if filter_options(x)]
110 return sorted(json, key=lambda x: x["name"])
111
112
113 def print_help(options):
114 print("meson_options_help() {")
115 for opt in options:
116 key = opt["name"].replace("_", "-")
117 # The first section includes options that have an arguments,
118 # and booleans (i.e., only one of enable/disable makes sense)
119 if opt["type"] == "boolean":
120 left = f"--disable-{key}" if opt["value"] else f"--enable-{key}"
121 help_line(left, opt, 27, False)
122 elif allow_arg(opt):
123 if opt["type"] == "combo" and "enabled" in opt["choices"]:
124 left = f"--enable-{key}[=CHOICE]"
125 else:
126 left = f"--enable-{key}=CHOICE"
127 help_line(left, opt, 27, True)
128
129 sh_print()
130 sh_print("Optional features, enabled with --enable-FEATURE and")
131 sh_print("disabled with --disable-FEATURE, default is enabled if available")
132 sh_print("(unless built with --without-default-features):")
133 sh_print()
134 for opt in options:
135 key = opt["name"].replace("_", "-")
136 if opt["type"] != "boolean" and not allow_arg(opt):
137 help_line(key, opt, 18, False)
138 print("}")
139
140
141 def print_parse(options):
142 print("_meson_option_parse() {")
143 print(" case $1 in")
144 for opt in options:
145 key = opt["name"].replace("_", "-")
146 name = opt["name"]
147 if opt["type"] == "boolean":
148 print(f' --enable-{key}) printf "%s" -D{name}=true ;;')
149 print(f' --disable-{key}) printf "%s" -D{name}=false ;;')
150 else:
151 if opt["type"] == "combo" and "enabled" in opt["choices"]:
152 print(f' --enable-{key}) printf "%s" -D{name}=enabled ;;')
153 if opt["type"] == "combo" and "disabled" in opt["choices"]:
154 print(f' --disable-{key}) printf "%s" -D{name}=disabled ;;')
155 if allow_arg(opt):
156 print(f' --enable-{key}=*) quote_sh "-D{name}=$2" ;;')
157 print(" *) return 1 ;;")
158 print(" esac")
159 print("}")
160
161
162 options = load_options(json.load(sys.stdin))
163 print("# This file is generated by meson-buildoptions.py, do not edit!")
164 print_help(options)
165 print_parse(options)