]>
Commit | Line | Data |
---|---|---|
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 | ||
23 | import json | |
24 | import textwrap | |
25 | import shlex | |
26 | import sys | |
27 | ||
3b4da132 PB |
28 | SKIP_OPTIONS = { |
29 | "audio_drv_list", | |
30 | "default_devices", | |
31 | "docdir", | |
32 | "fuzzing_engine", | |
33 | "qemu_firmwarepath", | |
34 | "qemu_suffix", | |
35 | "sphinx_build", | |
36 | "trace_file", | |
37 | } | |
38 | ||
39 | LINE_WIDTH = 76 | |
40 | ||
41 | ||
42 | # Convert the default value of an option to the string used in | |
43 | # the help message | |
44 | def value_to_help(value): | |
45 | if isinstance(value, list): | |
46 | return ",".join(value) | |
47 | if isinstance(value, bool): | |
48 | return "enabled" if value else "disabled" | |
49 | return str(value) | |
50 | ||
51 | ||
52 | def wrap(left, text, indent): | |
53 | spaces = " " * indent | |
54 | if len(left) >= indent: | |
55 | yield left | |
56 | left = spaces | |
57 | else: | |
58 | left = (left + spaces)[0:indent] | |
59 | yield from textwrap.wrap( | |
60 | text, width=LINE_WIDTH, initial_indent=left, subsequent_indent=spaces | |
61 | ) | |
62 | ||
63 | ||
61d63097 PB |
64 | def sh_print(line=""): |
65 | print(' printf "%s\\n"', shlex.quote(line)) | |
66 | ||
67 | ||
3b4da132 PB |
68 | def help_line(left, opt, indent, long): |
69 | right = f'{opt["description"]}' | |
70 | if long: | |
71 | value = value_to_help(opt["value"]) | |
72 | if value != "auto": | |
73 | right += f" [{value}]" | |
74 | if "choices" in opt and long: | |
75 | choices = "/".join(sorted(opt["choices"])) | |
76 | right += f" (choices: {choices})" | |
77 | for x in wrap(" " + left, right, indent): | |
78 | sh_print(x) | |
79 | ||
80 | ||
81 | # Return whether the option (a dictionary) can be used with | |
82 | # arguments. Booleans can never be used with arguments; | |
83 | # combos allow an argument only if they accept other values | |
84 | # than "auto", "enabled", and "disabled". | |
85 | def allow_arg(opt): | |
86 | if opt["type"] == "boolean": | |
87 | return False | |
88 | if opt["type"] != "combo": | |
89 | return True | |
90 | return not (set(opt["choices"]) <= {"auto", "disabled", "enabled"}) | |
91 | ||
92 | ||
61d63097 PB |
93 | def load_options(json): |
94 | json = [ | |
95 | x | |
96 | for x in json | |
97 | if x["section"] == "user" | |
98 | and ":" not in x["name"] | |
99 | and x["name"] not in SKIP_OPTIONS | |
100 | ] | |
101 | return sorted(json, key=lambda x: x["name"]) | |
102 | ||
103 | ||
104 | def print_help(options): | |
105 | print("meson_options_help() {") | |
3b4da132 PB |
106 | for opt in options: |
107 | key = opt["name"].replace("_", "-") | |
108 | # The first section includes options that have an arguments, | |
109 | # and booleans (i.e., only one of enable/disable makes sense) | |
110 | if opt["type"] == "boolean": | |
111 | left = f"--disable-{key}" if opt["value"] else f"--enable-{key}" | |
112 | help_line(left, opt, 27, False) | |
113 | elif allow_arg(opt): | |
114 | if opt["type"] == "combo" and "enabled" in opt["choices"]: | |
115 | left = f"--enable-{key}[=CHOICE]" | |
116 | else: | |
117 | left = f"--enable-{key}=CHOICE" | |
118 | help_line(left, opt, 27, True) | |
119 | ||
61d63097 PB |
120 | sh_print() |
121 | sh_print("Optional features, enabled with --enable-FEATURE and") | |
122 | sh_print("disabled with --disable-FEATURE, default is enabled if available") | |
123 | sh_print("(unless built with --without-default-features):") | |
124 | sh_print() | |
3b4da132 PB |
125 | for opt in options: |
126 | key = opt["name"].replace("_", "-") | |
127 | if opt["type"] != "boolean" and not allow_arg(opt): | |
128 | help_line(key, opt, 18, False) | |
61d63097 PB |
129 | print("}") |
130 | ||
131 | ||
132 | def print_parse(options): | |
133 | print("_meson_option_parse() {") | |
134 | print(" case $1 in") | |
3b4da132 PB |
135 | for opt in options: |
136 | key = opt["name"].replace("_", "-") | |
137 | name = opt["name"] | |
138 | if opt["type"] == "boolean": | |
139 | print(f' --enable-{key}) printf "%s" -D{name}=true ;;') | |
140 | print(f' --disable-{key}) printf "%s" -D{name}=false ;;') | |
141 | else: | |
142 | if opt["type"] == "combo" and "enabled" in opt["choices"]: | |
143 | print(f' --enable-{key}) printf "%s" -D{name}=enabled ;;') | |
144 | if opt["type"] == "combo" and "disabled" in opt["choices"]: | |
145 | print(f' --disable-{key}) printf "%s" -D{name}=disabled ;;') | |
146 | if allow_arg(opt): | |
147 | print(f' --enable-{key}=*) quote_sh "-D{name}=$2" ;;') | |
61d63097 PB |
148 | print(" *) return 1 ;;") |
149 | print(" esac") | |
150 | print("}") | |
151 | ||
152 | ||
153 | options = load_options(json.load(sys.stdin)) | |
154 | print("# This file is generated by meson-buildoptions.py, do not edit!") | |
155 | print_help(options) | |
156 | print_parse(options) |