Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:10:04

0001 #!/usr/bin/env python3
0002 """
0003 This script accepts a cmake lists file as an argument extracts all
0004 `option` and `set(... CACHE ...)` variables. It then writes a
0005 markdown table to stdout
0006 """
0007 
0008 import argparse
0009 from pathlib import Path
0010 import re
0011 import textwrap
0012 import sys
0013 import difflib
0014 
0015 p = argparse.ArgumentParser(description=__doc__)
0016 
0017 p.add_argument("cmakefile", help="Input cmake lists file to parse")
0018 p.add_argument(
0019     "--prefix", default="ACTS_", help="Prefix to identify relevant variables to extract"
0020 )
0021 p.add_argument(
0022     "--width",
0023     type=int,
0024     default=40,
0025     help="Width of second column generated from cmake doc strings",
0026 )
0027 p.add_argument(
0028     "--write",
0029     "-w",
0030     help="Write table to this file, expects delimiters CMAKE_OPTS_{BEGIN,END}",
0031     type=Path,
0032 )
0033 p.add_argument(
0034     "--verify",
0035     "-v",
0036     help="Only verify the target file contains the right table, don't write",
0037     action="store_true",
0038 )
0039 
0040 
0041 args = p.parse_args()
0042 
0043 cmakefile = Path(args.cmakefile)
0044 
0045 with cmakefile.open() as fh:
0046     opts = {}
0047     rows = []
0048     for line in fh:
0049         if m := re.match(
0050             rf"option\( *({args.prefix}\w*) \"(.*)\" (ON|OFF|\${{\w+}})\ *\)", line
0051         ):
0052             name, doc, default = m.groups()
0053             type = "bool"
0054             if m := re.match(r"\${(\w+)}", default):
0055                 lookup = m.group(1)
0056                 if lookup in opts:
0057                     default = f"{lookup} -> {opts[lookup]}"
0058         elif m := re.match(
0059             rf"set\( *({args.prefix}\w*) \"(.*)\" CACHE (\w+) \"(.*)\"( FORCE)? *\)",
0060             line,
0061         ):
0062             name, default, type, doc, _ = m.groups()
0063             type = type.lower()
0064             if default == "":
0065                 default = '""'
0066         else:
0067             continue
0068 
0069         opts[name] = default
0070         doc = "<br>".join(textwrap.wrap(doc, width=args.width))
0071         rows.append((name, f"{doc}<br> type: `{type}`, default: `{default}`"))
0072 
0073 output = ""
0074 
0075 headers = ("Option", "Description")
0076 column_lengths = [0] * len(rows[0])
0077 
0078 for row in rows:
0079     for i, col in enumerate(row):
0080         column_lengths[i] = max(column_lengths[i], len(col))
0081 
0082 output += "|"
0083 for i, header in enumerate(headers):
0084     output += " " + header.ljust(column_lengths[i]) + " |"
0085 output += "\n"
0086 
0087 output += "|"
0088 for i in range(len(column_lengths)):
0089     output += "-" + ("-" * column_lengths[i]) + "-|"
0090 output += "\n"
0091 
0092 
0093 for row in rows:
0094     output += "|"
0095     for i, col in enumerate(row):
0096         output += " " + col.ljust(column_lengths[i]) + " |"
0097     output += "\n"
0098 
0099 output = output.strip()
0100 
0101 if args.write and args.write.exists():
0102     source = args.write.read_text().split("\n")
0103     try:
0104         begin = source.index("<!-- CMAKE_OPTS_BEGIN -->")
0105         end = source.index("<!-- CMAKE_OPTS_END -->")
0106     except ValueError:
0107         print("Markers not found in output file")
0108         sys.exit(1)
0109 
0110     if args.verify:
0111         actual = "\n".join(source[begin + 1 : end])
0112         if output != actual:
0113             print("MISMATCH:\n" + "-" * 9 + "\n")
0114             print(
0115                 "\n".join(
0116                     difflib.unified_diff(
0117                         actual.split("\n"),
0118                         output.split("\n"),
0119                         fromfile="actual",
0120                         tofile="output",
0121                     )
0122                 )
0123             )
0124             sys.exit(1)
0125     elif args.write:
0126         out = source[: begin + 1] + output.split("\n") + source[end:]
0127         args.write.write_text("\n".join(out))
0128 else:
0129     print(output)