]> git.proxmox.com Git - mirror_qemu.git/blame - scripts/meson-buildoptions.py
configure: move Windows flags detection to meson
[mirror_qemu.git] / scripts / meson-buildoptions.py
CommitLineData
61d63097
PB
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
23import json
24import textwrap
25import shlex
26import sys
27
3b4da132
PB
28SKIP_OPTIONS = {
29 "audio_drv_list",
30 "default_devices",
31 "docdir",
32 "fuzzing_engine",
5dc4618e 33 "iasl",
3b4da132
PB
34 "qemu_firmwarepath",
35 "qemu_suffix",
35acbb30 36 "smbd",
3b4da132
PB
37 "sphinx_build",
38 "trace_file",
39}
40
119fc611
PB
41OPTION_NAMES = {
42 "malloc": "enable-malloc",
43 "trace_backends": "enable-trace-backends",
44}
45
a70248db
PB
46BUILTIN_OPTIONS = {
47 "strip",
48}
49
3b4da132
PB
50LINE_WIDTH = 76
51
52
53# Convert the default value of an option to the string used in
54# the help message
55def value_to_help(value):
56 if isinstance(value, list):
57 return ",".join(value)
58 if isinstance(value, bool):
59 return "enabled" if value else "disabled"
60 return str(value)
61
62
63def wrap(left, text, indent):
64 spaces = " " * indent
65 if len(left) >= indent:
66 yield left
67 left = spaces
68 else:
69 left = (left + spaces)[0:indent]
70 yield from textwrap.wrap(
71 text, width=LINE_WIDTH, initial_indent=left, subsequent_indent=spaces
72 )
73
74
61d63097
PB
75def sh_print(line=""):
76 print(' printf "%s\\n"', shlex.quote(line))
77
78
3b4da132
PB
79def help_line(left, opt, indent, long):
80 right = f'{opt["description"]}'
81 if long:
82 value = value_to_help(opt["value"])
119fc611 83 if value != "auto" and value != "":
3b4da132
PB
84 right += f" [{value}]"
85 if "choices" in opt and long:
86 choices = "/".join(sorted(opt["choices"]))
87 right += f" (choices: {choices})"
88 for x in wrap(" " + left, right, indent):
89 sh_print(x)
90
91
92# Return whether the option (a dictionary) can be used with
93# arguments. Booleans can never be used with arguments;
94# combos allow an argument only if they accept other values
95# than "auto", "enabled", and "disabled".
96def allow_arg(opt):
97 if opt["type"] == "boolean":
98 return False
99 if opt["type"] != "combo":
100 return True
101 return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"})
102
103
119fc611
PB
104# Return whether the option (a dictionary) can be used without
105# arguments. Booleans can only be used without arguments;
106# combos require an argument if they accept neither "enabled"
107# nor "disabled"
108def require_arg(opt):
109 if opt["type"] == "boolean":
110 return False
111 if opt["type"] != "combo":
112 return True
113 return not ({"enabled", "disabled"}.intersection(opt["choices"]))
114
115
a70248db
PB
116def filter_options(json):
117 if ":" in json["name"]:
118 return False
119 if json["section"] == "user":
120 return json["name"] not in SKIP_OPTIONS
121 else:
122 return json["name"] in BUILTIN_OPTIONS
123
124
61d63097 125def load_options(json):
a70248db 126 json = [x for x in json if filter_options(x)]
61d63097
PB
127 return sorted(json, key=lambda x: x["name"])
128
129
119fc611
PB
130def cli_option(opt):
131 name = opt["name"]
132 if name in OPTION_NAMES:
133 return OPTION_NAMES[name]
134 return name.replace("_", "-")
135
136
137def cli_help_key(opt):
138 key = cli_option(opt)
139 if require_arg(opt):
140 return key
141 if opt["type"] == "boolean" and opt["value"]:
142 return f"disable-{key}"
143 return f"enable-{key}"
144
145
146def cli_metavar(opt):
147 if opt["type"] == "string":
148 return "VALUE"
149 if opt["type"] == "array":
150 return "CHOICES"
151 return "CHOICE"
152
153
61d63097
PB
154def print_help(options):
155 print("meson_options_help() {")
119fc611
PB
156 for opt in sorted(options, key=cli_help_key):
157 key = cli_help_key(opt)
3b4da132
PB
158 # The first section includes options that have an arguments,
159 # and booleans (i.e., only one of enable/disable makes sense)
119fc611
PB
160 if require_arg(opt):
161 metavar = cli_metavar(opt)
162 left = f"--{key}={metavar}"
163 help_line(left, opt, 27, True)
164 elif opt["type"] == "boolean":
165 left = f"--{key}"
3b4da132
PB
166 help_line(left, opt, 27, False)
167 elif allow_arg(opt):
168 if opt["type"] == "combo" and "enabled" in opt["choices"]:
119fc611 169 left = f"--{key}[=CHOICE]"
3b4da132 170 else:
119fc611 171 left = f"--{key}=CHOICE"
3b4da132
PB
172 help_line(left, opt, 27, True)
173
61d63097
PB
174 sh_print()
175 sh_print("Optional features, enabled with --enable-FEATURE and")
176 sh_print("disabled with --disable-FEATURE, default is enabled if available")
177 sh_print("(unless built with --without-default-features):")
178 sh_print()
3b4da132
PB
179 for opt in options:
180 key = opt["name"].replace("_", "-")
181 if opt["type"] != "boolean" and not allow_arg(opt):
182 help_line(key, opt, 18, False)
61d63097
PB
183 print("}")
184
185
186def print_parse(options):
187 print("_meson_option_parse() {")
188 print(" case $1 in")
3b4da132 189 for opt in options:
119fc611 190 key = cli_option(opt)
3b4da132 191 name = opt["name"]
119fc611
PB
192 if require_arg(opt):
193 print(f' --{key}=*) quote_sh "-D{name}=$2" ;;')
194 elif opt["type"] == "boolean":
3b4da132
PB
195 print(f' --enable-{key}) printf "%s" -D{name}=true ;;')
196 print(f' --disable-{key}) printf "%s" -D{name}=false ;;')
197 else:
198 if opt["type"] == "combo" and "enabled" in opt["choices"]:
199 print(f' --enable-{key}) printf "%s" -D{name}=enabled ;;')
200 if opt["type"] == "combo" and "disabled" in opt["choices"]:
201 print(f' --disable-{key}) printf "%s" -D{name}=disabled ;;')
202 if allow_arg(opt):
203 print(f' --enable-{key}=*) quote_sh "-D{name}=$2" ;;')
61d63097
PB
204 print(" *) return 1 ;;")
205 print(" esac")
206 print("}")
207
208
209options = load_options(json.load(sys.stdin))
210print("# This file is generated by meson-buildoptions.py, do not edit!")
211print_help(options)
212print_parse(options)