150 lines
5.2 KiB
Python
150 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
# A tool to parse the output of `llvm-bolt --help-hidden` and update the
|
|
# documentation in CommandLineArgumentReference.md automatically.
|
|
# Run from the directory in which this file is located to update the docs.
|
|
|
|
import subprocess
|
|
from textwrap import wrap
|
|
|
|
LINE_LIMIT = 80
|
|
|
|
|
|
def wrap_text(text, indent, limit=LINE_LIMIT):
|
|
wrapped_lines = wrap(text, width=limit - len(indent))
|
|
wrapped_text = ("\n" + indent).join(wrapped_lines)
|
|
return wrapped_text
|
|
|
|
|
|
def add_info(sections, section, option, description):
|
|
indent = " "
|
|
wrapped_description = "\n".join(
|
|
[
|
|
wrap_text(line, indent) if len(line) > LINE_LIMIT else line
|
|
for line in description
|
|
]
|
|
)
|
|
sections[section].append((option, indent + wrapped_description))
|
|
|
|
|
|
def parse_bolt_options(output):
|
|
section_headers = [
|
|
"Generic options:",
|
|
"Output options:",
|
|
"BOLT generic options:",
|
|
"BOLT optimization options:",
|
|
"BOLT options in relocation mode:",
|
|
"BOLT instrumentation options:",
|
|
"BOLT printing options:",
|
|
]
|
|
|
|
sections = {key: [] for key in section_headers}
|
|
current_section, prev_section = None, None
|
|
option, description = None, []
|
|
|
|
for line in output.split("\n"):
|
|
cleaned_line = line.strip()
|
|
|
|
if cleaned_line.casefold() in map(str.casefold, section_headers):
|
|
if prev_section != None: # Save last option from prev section
|
|
add_info(sections, current_section, option, description)
|
|
option, description = None, []
|
|
|
|
cleaned_line = cleaned_line.split()
|
|
# Apply lowercase to all words except the first one
|
|
cleaned_line = [cleaned_line[0]] + [
|
|
word.lower() for word in cleaned_line[1:]
|
|
]
|
|
# Join the words back together into a string
|
|
cleaned_line = " ".join(cleaned_line)
|
|
|
|
current_section = cleaned_line
|
|
prev_section = current_section
|
|
continue
|
|
|
|
if cleaned_line.startswith("-"):
|
|
if option and description:
|
|
# Join description lines, adding an extra newline for
|
|
# sub-options that start with '='
|
|
add_info(sections, current_section, option, description)
|
|
option, description = None, []
|
|
|
|
parts = cleaned_line.split(" ", 1)
|
|
if len(parts) > 1:
|
|
option = parts[0].strip()
|
|
descr = parts[1].strip()
|
|
descr = descr[2].upper() + descr[3:]
|
|
description = [descr]
|
|
if option.startswith("--print") or option.startswith("--time"):
|
|
current_section = "BOLT printing options:"
|
|
elif prev_section != None:
|
|
current_section = prev_section
|
|
continue
|
|
|
|
if cleaned_line.startswith("="):
|
|
parts = cleaned_line.split(maxsplit=1)
|
|
# Split into two parts: sub-option and description
|
|
if len(parts) == 2:
|
|
# Rejoin with a single space
|
|
cleaned_line = parts[0] + " " + parts[1].rstrip()
|
|
description.append(cleaned_line)
|
|
elif cleaned_line: # Multiline description continuation
|
|
description.append(cleaned_line)
|
|
|
|
add_info(sections, current_section, option, description)
|
|
return sections
|
|
|
|
|
|
def generate_markdown(sections):
|
|
markdown_lines = [
|
|
"# BOLT - a post-link optimizer developed to speed up large applications\n",
|
|
"## SYNOPSIS\n",
|
|
"`llvm-bolt <executable> [-o outputfile] <executable>.bolt "
|
|
"[-data=perf.fdata] [options]`\n",
|
|
"## OPTIONS",
|
|
]
|
|
|
|
for section, options in sections.items():
|
|
markdown_lines.append(f"\n### {section}")
|
|
if section == "BOLT instrumentation options:":
|
|
markdown_lines.append(
|
|
f"\n`llvm-bolt <executable> -instrument"
|
|
" [-o outputfile] <instrumented-executable>`"
|
|
)
|
|
for option, desc in options:
|
|
markdown_lines.append(f"\n- `{option}`\n")
|
|
# Split description into lines to handle sub-options
|
|
desc_lines = desc.split("\n")
|
|
for line in desc_lines:
|
|
if line.startswith("="):
|
|
# Sub-option: correct formatting with bullet
|
|
sub_option, sub_desc = line[1:].split(" ", 1)
|
|
markdown_lines.append(f" - `{sub_option}`: {sub_desc[4:]}")
|
|
else:
|
|
# Regular line of description
|
|
if line[2:].startswith("<"):
|
|
line = line.replace("<", "").replace(">", "")
|
|
markdown_lines.append(f"{line}")
|
|
|
|
return "\n".join(markdown_lines)
|
|
|
|
|
|
def main():
|
|
try:
|
|
help_output = subprocess.run(
|
|
["llvm-bolt", "--help-hidden"], capture_output=True, text=True, check=True
|
|
).stdout
|
|
except subprocess.CalledProcessError as e:
|
|
print("Failed to execute llvm-bolt --help:")
|
|
print(e)
|
|
return
|
|
|
|
sections = parse_bolt_options(help_output)
|
|
markdown = generate_markdown(sections)
|
|
|
|
with open("CommandLineArgumentReference.md", "w") as md_file:
|
|
md_file.write(markdown)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|