16ad0dcf6SRoland McGrath#!/usr/bin/env python3 26ad0dcf6SRoland McGrath# 36ad0dcf6SRoland McGrath# ===- Generate headers for libc functions ------------------*- python -*--==# 46ad0dcf6SRoland McGrath# 56ad0dcf6SRoland McGrath# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 66ad0dcf6SRoland McGrath# See https://llvm.org/LICENSE.txt for license information. 76ad0dcf6SRoland McGrath# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 86ad0dcf6SRoland McGrath# 96ad0dcf6SRoland McGrath# ==------------------------------------------------------------------------==# 106ad0dcf6SRoland McGrath 116ad0dcf6SRoland McGrathimport argparse 126ad0dcf6SRoland McGrathimport sys 136ad0dcf6SRoland McGrathfrom pathlib import Path 146ad0dcf6SRoland McGrath 156ad0dcf6SRoland McGrathfrom header import HeaderFile 166ad0dcf6SRoland McGrathfrom yaml_to_classes import load_yaml_file, fill_public_api 176ad0dcf6SRoland McGrath 186ad0dcf6SRoland McGrath 196ad0dcf6SRoland McGrathdef main(): 206ad0dcf6SRoland McGrath parser = argparse.ArgumentParser(description="Generate header files from YAML") 216ad0dcf6SRoland McGrath parser.add_argument( 226ad0dcf6SRoland McGrath "yaml_file", 236ad0dcf6SRoland McGrath help="Path to the YAML file containing header specification", 246ad0dcf6SRoland McGrath metavar="FILE", 256ad0dcf6SRoland McGrath type=Path, 266ad0dcf6SRoland McGrath nargs=1, 276ad0dcf6SRoland McGrath ) 286ad0dcf6SRoland McGrath parser.add_argument( 296ad0dcf6SRoland McGrath "-o", 306ad0dcf6SRoland McGrath "--output", 316ad0dcf6SRoland McGrath help="Path to write generated header file", 326ad0dcf6SRoland McGrath type=Path, 336ad0dcf6SRoland McGrath required=True, 346ad0dcf6SRoland McGrath ) 356ad0dcf6SRoland McGrath parser.add_argument( 366ad0dcf6SRoland McGrath "--depfile", 376ad0dcf6SRoland McGrath help="Path to write a depfile", 386ad0dcf6SRoland McGrath type=Path, 396ad0dcf6SRoland McGrath ) 406ad0dcf6SRoland McGrath parser.add_argument( 41*cdbba15cSRoland McGrath "--write-if-changed", 42*cdbba15cSRoland McGrath help="Write the output file only if its contents have changed", 43*cdbba15cSRoland McGrath action="store_true", 44*cdbba15cSRoland McGrath default=False, 45*cdbba15cSRoland McGrath ) 46*cdbba15cSRoland McGrath parser.add_argument( 476ad0dcf6SRoland McGrath "-e", 486ad0dcf6SRoland McGrath "--entry-point", 496ad0dcf6SRoland McGrath help="Entry point to include; may be given many times", 506ad0dcf6SRoland McGrath metavar="SYMBOL", 516ad0dcf6SRoland McGrath action="append", 526ad0dcf6SRoland McGrath ) 536ad0dcf6SRoland McGrath args = parser.parse_args() 546ad0dcf6SRoland McGrath 556ad0dcf6SRoland McGrath [yaml_file] = args.yaml_file 566ad0dcf6SRoland McGrath files_read = {yaml_file} 576ad0dcf6SRoland McGrath 586ad0dcf6SRoland McGrath def write_depfile(): 596ad0dcf6SRoland McGrath if not args.depfile: 606ad0dcf6SRoland McGrath return 616ad0dcf6SRoland McGrath deps = " ".join(str(f) for f in sorted(files_read)) 626ad0dcf6SRoland McGrath args.depfile.parent.mkdir(parents=True, exist_ok=True) 636ad0dcf6SRoland McGrath with open(args.depfile, "w") as depfile: 646ad0dcf6SRoland McGrath depfile.write(f"{args.output}: {deps}\n") 656ad0dcf6SRoland McGrath 666ad0dcf6SRoland McGrath header = load_yaml_file(yaml_file, HeaderFile, args.entry_point) 676ad0dcf6SRoland McGrath 686ad0dcf6SRoland McGrath if not header.template_file: 696ad0dcf6SRoland McGrath print(f"{yaml_file}: Missing header_template", sys.stderr) 706ad0dcf6SRoland McGrath return 2 716ad0dcf6SRoland McGrath 726ad0dcf6SRoland McGrath # The header_template path is relative to the containing YAML file. 736ad0dcf6SRoland McGrath template_path = yaml_file.parent / header.template_file 746ad0dcf6SRoland McGrath 756ad0dcf6SRoland McGrath files_read.add(template_path) 766ad0dcf6SRoland McGrath with open(template_path) as template: 776ad0dcf6SRoland McGrath contents = fill_public_api(header.public_api(), template.read()) 786ad0dcf6SRoland McGrath 796ad0dcf6SRoland McGrath write_depfile() 806ad0dcf6SRoland McGrath 81*cdbba15cSRoland McGrath if ( 82*cdbba15cSRoland McGrath not args.write_if_changed 83*cdbba15cSRoland McGrath or not args.output.exists() 84*cdbba15cSRoland McGrath or args.output.read_text() != contents 85*cdbba15cSRoland McGrath ): 866ad0dcf6SRoland McGrath args.output.parent.mkdir(parents=True, exist_ok=True) 87*cdbba15cSRoland McGrath args.output.write_text(contents) 886ad0dcf6SRoland McGrath 896ad0dcf6SRoland McGrath 906ad0dcf6SRoland McGrathif __name__ == "__main__": 916ad0dcf6SRoland McGrath sys.exit(main()) 92