Bump version to 19.1.0 (final)
[llvm-project.git] / bolt / docs / generate_doc.py
blob763dc00b44ca31e33a335b9cd85c555edb74af9f
1 #!/usr/bin/env python3
2 # A tool to parse the output of `llvm-bolt --help-hidden` and update the
3 # documentation in CommandLineArgumentReference.md automatically.
4 # Run from the directory in which this file is located to update the docs.
6 import subprocess
7 from textwrap import wrap
9 LINE_LIMIT = 80
12 def wrap_text(text, indent, limit=LINE_LIMIT):
13 wrapped_lines = wrap(text, width=limit - len(indent))
14 wrapped_text = ("\n" + indent).join(wrapped_lines)
15 return wrapped_text
18 def add_info(sections, section, option, description):
19 indent = " "
20 wrapped_description = "\n".join(
22 wrap_text(line, indent) if len(line) > LINE_LIMIT else line
23 for line in description
26 sections[section].append((option, indent + wrapped_description))
29 def parse_bolt_options(output):
30 section_headers = [
31 "Generic options:",
32 "Output options:",
33 "BOLT generic options:",
34 "BOLT optimization options:",
35 "BOLT options in relocation mode:",
36 "BOLT instrumentation options:",
37 "BOLT printing options:",
40 sections = {key: [] for key in section_headers}
41 current_section, prev_section = None, None
42 option, description = None, []
44 for line in output.split("\n"):
45 cleaned_line = line.strip()
47 if cleaned_line.casefold() in map(str.casefold, section_headers):
48 if prev_section is not None: # Save last option from prev section
49 add_info(sections, current_section, option, description)
50 option, description = None, []
52 cleaned_line = cleaned_line.split()
53 # Apply lowercase to all words except the first one
54 cleaned_line = [cleaned_line[0]] + [
55 word.lower() for word in cleaned_line[1:]
57 # Join the words back together into a string
58 cleaned_line = " ".join(cleaned_line)
60 current_section = cleaned_line
61 prev_section = current_section
62 continue
64 if cleaned_line.startswith("-"):
65 if option and description:
66 # Join description lines, adding an extra newline for
67 # sub-options that start with '='
68 add_info(sections, current_section, option, description)
69 option, description = None, []
71 parts = cleaned_line.split(" ", 1)
72 if len(parts) > 1:
73 option = parts[0].strip()
74 descr = parts[1].strip()
75 descr = descr[2].upper() + descr[3:]
76 description = [descr]
77 if option.startswith("--print") or option.startswith("--time"):
78 current_section = "BOLT printing options:"
79 elif prev_section is not None:
80 current_section = prev_section
81 continue
83 if cleaned_line.startswith("="):
84 parts = cleaned_line.split(maxsplit=1)
85 # Split into two parts: sub-option and description
86 if len(parts) == 2:
87 # Rejoin with a single space
88 cleaned_line = parts[0] + " " + parts[1].rstrip()
89 description.append(cleaned_line)
90 elif cleaned_line: # Multiline description continuation
91 description.append(cleaned_line)
93 add_info(sections, current_section, option, description)
94 return sections
97 def generate_markdown(sections):
98 markdown_lines = [
99 "# BOLT - a post-link optimizer developed to speed up large applications\n",
100 "## SYNOPSIS\n",
101 "`llvm-bolt <executable> [-o outputfile] <executable>.bolt "
102 "[-data=perf.fdata] [options]`\n",
103 "## OPTIONS",
106 for section, options in sections.items():
107 markdown_lines.append(f"\n### {section}")
108 if section == "BOLT instrumentation options:":
109 markdown_lines.append(
110 f"\n`llvm-bolt <executable> -instrument"
111 " [-o outputfile] <instrumented-executable>`"
113 for option, desc in options:
114 markdown_lines.append(f"\n- `{option}`\n")
115 # Split description into lines to handle sub-options
116 desc_lines = desc.split("\n")
117 for line in desc_lines:
118 if line.startswith("="):
119 # Sub-option: correct formatting with bullet
120 sub_option, sub_desc = line[1:].split(" ", 1)
121 markdown_lines.append(f" - `{sub_option}`: {sub_desc[4:]}")
122 else:
123 # Regular line of description
124 if line[2:].startswith("<"):
125 line = line.replace("<", "").replace(">", "")
126 markdown_lines.append(f"{line}")
128 return "\n".join(markdown_lines)
131 def main():
132 try:
133 help_output = subprocess.run(
134 ["llvm-bolt", "--help-hidden"], capture_output=True, text=True, check=True
135 ).stdout
136 except subprocess.CalledProcessError as e:
137 print("Failed to execute llvm-bolt --help:")
138 print(e)
139 return
141 sections = parse_bolt_options(help_output)
142 markdown = generate_markdown(sections)
144 with open("CommandLineArgumentReference.md", "w") as md_file:
145 md_file.write(markdown)
148 if __name__ == "__main__":
149 main()