1#!/usr/bin/env python3 2# 3# ===- Generate headers for libc functions ------------------*- python -*--==# 4# 5# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6# See https://llvm.org/LICENSE.txt for license information. 7# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8# 9# ==------------------------------------------------------------------------==# 10 11import argparse 12import sys 13from pathlib import Path 14 15from header import HeaderFile 16from yaml_to_classes import load_yaml_file, fill_public_api 17 18 19def main(): 20 parser = argparse.ArgumentParser(description="Generate header files from YAML") 21 parser.add_argument( 22 "yaml_file", 23 help="Path to the YAML file containing header specification", 24 metavar="FILE", 25 type=Path, 26 nargs=1, 27 ) 28 parser.add_argument( 29 "-o", 30 "--output", 31 help="Path to write generated header file", 32 type=Path, 33 required=True, 34 ) 35 parser.add_argument( 36 "--depfile", 37 help="Path to write a depfile", 38 type=Path, 39 ) 40 parser.add_argument( 41 "--write-if-changed", 42 help="Write the output file only if its contents have changed", 43 action="store_true", 44 default=False, 45 ) 46 parser.add_argument( 47 "-e", 48 "--entry-point", 49 help="Entry point to include; may be given many times", 50 metavar="SYMBOL", 51 action="append", 52 ) 53 args = parser.parse_args() 54 55 [yaml_file] = args.yaml_file 56 files_read = {yaml_file} 57 58 def write_depfile(): 59 if not args.depfile: 60 return 61 deps = " ".join(str(f) for f in sorted(files_read)) 62 args.depfile.parent.mkdir(parents=True, exist_ok=True) 63 with open(args.depfile, "w") as depfile: 64 depfile.write(f"{args.output}: {deps}\n") 65 66 header = load_yaml_file(yaml_file, HeaderFile, args.entry_point) 67 68 if not header.template_file: 69 print(f"{yaml_file}: Missing header_template", sys.stderr) 70 return 2 71 72 # The header_template path is relative to the containing YAML file. 73 template_path = yaml_file.parent / header.template_file 74 75 files_read.add(template_path) 76 with open(template_path) as template: 77 contents = fill_public_api(header.public_api(), template.read()) 78 79 write_depfile() 80 81 if ( 82 not args.write_if_changed 83 or not args.output.exists() 84 or args.output.read_text() != contents 85 ): 86 args.output.parent.mkdir(parents=True, exist_ok=True) 87 args.output.write_text(contents) 88 89 90if __name__ == "__main__": 91 sys.exit(main()) 92