150 lines · python
1#!/usr/bin/env python32# A tool to parse the output of `llvm-bolt --help-hidden` and update the3# documentation in CommandLineArgumentReference.md automatically.4# Run from the directory in which this file is located to update the docs.5 6import subprocess7from textwrap import wrap8 9LINE_LIMIT = 8010 11 12def 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_text16 17 18def add_info(sections, section, option, description):19 indent = " "20 wrapped_description = "\n".join(21 [22 wrap_text(line, indent) if len(line) > LINE_LIMIT else line23 for line in description24 ]25 )26 sections[section].append((option, indent + wrapped_description))27 28 29def 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:",38 ]39 40 sections = {key: [] for key in section_headers}41 current_section, prev_section = None, None42 option, description = None, []43 44 for line in output.split("\n"):45 cleaned_line = line.strip()46 47 if cleaned_line.casefold() in map(str.casefold, section_headers):48 if prev_section is not None: # Save last option from prev section49 add_info(sections, current_section, option, description)50 option, description = None, []51 52 cleaned_line = cleaned_line.split()53 # Apply lowercase to all words except the first one54 cleaned_line = [cleaned_line[0]] + [55 word.lower() for word in cleaned_line[1:]56 ]57 # Join the words back together into a string58 cleaned_line = " ".join(cleaned_line)59 60 current_section = cleaned_line61 prev_section = current_section62 continue63 64 if cleaned_line.startswith("-"):65 if option and description:66 # Join description lines, adding an extra newline for67 # sub-options that start with '='68 add_info(sections, current_section, option, description)69 option, description = None, []70 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_section81 continue82 83 if cleaned_line.startswith("="):84 parts = cleaned_line.split(maxsplit=1)85 # Split into two parts: sub-option and description86 if len(parts) == 2:87 # Rejoin with a single space88 cleaned_line = parts[0] + " " + parts[1].rstrip()89 description.append(cleaned_line)90 elif cleaned_line: # Multiline description continuation91 description.append(cleaned_line)92 93 add_info(sections, current_section, option, description)94 return sections95 96 97def 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",104 ]105 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>`"112 )113 for option, desc in options:114 markdown_lines.append(f"\n- `{option}`\n")115 # Split description into lines to handle sub-options116 desc_lines = desc.split("\n")117 for line in desc_lines:118 if line.startswith("="):119 # Sub-option: correct formatting with bullet120 sub_option, sub_desc = line[1:].split(" ", 1)121 markdown_lines.append(f" - `{sub_option}`: {sub_desc[4:]}")122 else:123 # Regular line of description124 if line[2:].startswith("<"):125 line = line.replace("<", "").replace(">", "")126 markdown_lines.append(f"{line}")127 128 return "\n".join(markdown_lines)129 130 131def main():132 try:133 help_output = subprocess.run(134 ["llvm-bolt", "--help-hidden"], capture_output=True, text=True, check=True135 ).stdout136 except subprocess.CalledProcessError as e:137 print("Failed to execute llvm-bolt --help:")138 print(e)139 return140 141 sections = parse_bolt_options(help_output)142 markdown = generate_markdown(sections)143 144 with open("CommandLineArgumentReference.md", "w") as md_file:145 md_file.write(markdown)146 147 148if __name__ == "__main__":149 main()150