1*3f982cf4SFabien Sanglard#!/usr/bin/env python3 2*3f982cf4SFabien Sanglard 3*3f982cf4SFabien Sanglard# Copyright 2018 The Chromium Authors. All rights reserved. 4*3f982cf4SFabien Sanglard# Use of this source code is governed by a BSD-style license that can be 5*3f982cf4SFabien Sanglard# found in the LICENSE file. 6*3f982cf4SFabien Sanglard 7*3f982cf4SFabien Sanglardimport argparse 8*3f982cf4SFabien Sanglardimport os 9*3f982cf4SFabien Sanglardimport subprocess 10*3f982cf4SFabien Sanglardimport sys 11*3f982cf4SFabien Sanglard 12*3f982cf4SFabien Sanglarddef main(): 13*3f982cf4SFabien Sanglard args = parseInput() 14*3f982cf4SFabien Sanglard 15*3f982cf4SFabien Sanglard assert validateHeaderInput(args.header), \ 16*3f982cf4SFabien Sanglard "Error: '%s' is not a valid .h file" % args.header 17*3f982cf4SFabien Sanglard assert validateCodeInput(args.cc), \ 18*3f982cf4SFabien Sanglard "Error: '%s' is not a valid .cc file" % args.cc 19*3f982cf4SFabien Sanglard assert validatePathInput(args.gen_dir), \ 20*3f982cf4SFabien Sanglard "Error: '%s' is not a valid output directory" % args.gen_dir 21*3f982cf4SFabien Sanglard assert validateCddlInput(args.file), \ 22*3f982cf4SFabien Sanglard "Error: '%s' is not a valid CDDL file" % args.file 23*3f982cf4SFabien Sanglard 24*3f982cf4SFabien Sanglard if args.log: 25*3f982cf4SFabien Sanglard logPath = os.path.join(args.gen_dir, args.log) 26*3f982cf4SFabien Sanglard log = open(logPath, "w") 27*3f982cf4SFabien Sanglard log.write("OUTPUT FOR CDDL CODE GENERATION TOOL:\n\n") 28*3f982cf4SFabien Sanglard log = open(logPath, "a") 29*3f982cf4SFabien Sanglard 30*3f982cf4SFabien Sanglard if (args.verbose): 31*3f982cf4SFabien Sanglard print("Logging to %s" % logPath) 32*3f982cf4SFabien Sanglard else: 33*3f982cf4SFabien Sanglard log = None 34*3f982cf4SFabien Sanglard 35*3f982cf4SFabien Sanglard if (args.verbose): 36*3f982cf4SFabien Sanglard print('Creating C++ files from provided CDDL file...') 37*3f982cf4SFabien Sanglard echoAndRunCommand([args.cddl, "--header", args.header, "--cc", args.cc, 38*3f982cf4SFabien Sanglard "--gen-dir", args.gen_dir, args.file], 39*3f982cf4SFabien Sanglard False, log, args.verbose) 40*3f982cf4SFabien Sanglard 41*3f982cf4SFabien Sanglard clangFormatLocation = findClangFormat() 42*3f982cf4SFabien Sanglard if not clangFormatLocation: 43*3f982cf4SFabien Sanglard if args.verbose: 44*3f982cf4SFabien Sanglard print("WARNING: clang-format could not be found") 45*3f982cf4SFabien Sanglard return 46*3f982cf4SFabien Sanglard 47*3f982cf4SFabien Sanglard for filename in [args.header, args.cc]: 48*3f982cf4SFabien Sanglard echoAndRunCommand([clangFormatLocation + 'clang-format', "-i", 49*3f982cf4SFabien Sanglard os.path.join(args.gen_dir, filename)], 50*3f982cf4SFabien Sanglard True, verbose=args.verbose) 51*3f982cf4SFabien Sanglard 52*3f982cf4SFabien Sanglarddef parseInput(): 53*3f982cf4SFabien Sanglard parser = argparse.ArgumentParser() 54*3f982cf4SFabien Sanglard parser.add_argument("--cddl", help="path to the cddl executable to use") 55*3f982cf4SFabien Sanglard parser.add_argument("--header", help="Specify the filename of the output \ 56*3f982cf4SFabien Sanglard header file. This is also the name that will be used for the include \ 57*3f982cf4SFabien Sanglard guard and as the include path in the source file.") 58*3f982cf4SFabien Sanglard parser.add_argument("--cc", help="Specify the filename of the output \ 59*3f982cf4SFabien Sanglard source file") 60*3f982cf4SFabien Sanglard parser.add_argument("--gen-dir", help="Specify the directory prefix that \ 61*3f982cf4SFabien Sanglard should be added to the output header and source file.") 62*3f982cf4SFabien Sanglard parser.add_argument("--log", help="Specify the file to which stdout should \ 63*3f982cf4SFabien Sanglard be redirected.") 64*3f982cf4SFabien Sanglard parser.add_argument("--verbose", help="Specify that we should log info \ 65*3f982cf4SFabien Sanglard messages to stdout") 66*3f982cf4SFabien Sanglard parser.add_argument("file", help="the input file which contains the spec") 67*3f982cf4SFabien Sanglard return parser.parse_args() 68*3f982cf4SFabien Sanglard 69*3f982cf4SFabien Sanglarddef validateHeaderInput(headerFile): 70*3f982cf4SFabien Sanglard return headerFile and headerFile.endswith('.h') 71*3f982cf4SFabien Sanglard 72*3f982cf4SFabien Sanglarddef validateCodeInput(ccFile): 73*3f982cf4SFabien Sanglard return ccFile and ccFile.endswith('.cc') 74*3f982cf4SFabien Sanglard 75*3f982cf4SFabien Sanglarddef validatePathInput(dirPath): 76*3f982cf4SFabien Sanglard return dirPath and os.path.isdir(dirPath) 77*3f982cf4SFabien Sanglard 78*3f982cf4SFabien Sanglarddef validateCddlInput(cddlFile): 79*3f982cf4SFabien Sanglard return cddlFile and os.path.isfile(cddlFile) 80*3f982cf4SFabien Sanglard 81*3f982cf4SFabien Sanglarddef echoAndRunCommand(commandArray, allowFailure, 82*3f982cf4SFabien Sanglard logfile = None, verbose = False): 83*3f982cf4SFabien Sanglard if verbose: 84*3f982cf4SFabien Sanglard print("\tExecuting Command: '%s'" % " ".join(commandArray)) 85*3f982cf4SFabien Sanglard 86*3f982cf4SFabien Sanglard if logfile != None: 87*3f982cf4SFabien Sanglard process = subprocess.Popen(commandArray, stdout=logfile, stderr=logfile) 88*3f982cf4SFabien Sanglard process.wait() 89*3f982cf4SFabien Sanglard logfile.flush() 90*3f982cf4SFabien Sanglard else: 91*3f982cf4SFabien Sanglard process = subprocess.Popen(commandArray) 92*3f982cf4SFabien Sanglard process.wait() 93*3f982cf4SFabien Sanglard 94*3f982cf4SFabien Sanglard returncode = process.returncode 95*3f982cf4SFabien Sanglard if returncode != None and returncode != 0: 96*3f982cf4SFabien Sanglard if not allowFailure: 97*3f982cf4SFabien Sanglard sys.exit("\t\tERROR: Command failed with error code: '%i'!" % returncode) 98*3f982cf4SFabien Sanglard elif verbose: 99*3f982cf4SFabien Sanglard print("\t\tWARNING: Command failed with error code: '%i'!" % returncode) 100*3f982cf4SFabien Sanglard 101*3f982cf4SFabien Sanglarddef findClangFormat(): 102*3f982cf4SFabien Sanglard executable = "clang-format" 103*3f982cf4SFabien Sanglard 104*3f982cf4SFabien Sanglard # Try and run from the environment variable 105*3f982cf4SFabien Sanglard for directory in os.environ["PATH"].split(os.pathsep): 106*3f982cf4SFabien Sanglard fullPath = os.path.join(directory, executable) 107*3f982cf4SFabien Sanglard if os.path.isfile(fullPath): 108*3f982cf4SFabien Sanglard return "" 109*3f982cf4SFabien Sanglard 110*3f982cf4SFabien Sanglard # Check 2 levels up since this should be correct on the build machine 111*3f982cf4SFabien Sanglard path = "../../" 112*3f982cf4SFabien Sanglard fullPath = os.path.join(path, executable) 113*3f982cf4SFabien Sanglard if os.path.isfile(fullPath): 114*3f982cf4SFabien Sanglard return path 115*3f982cf4SFabien Sanglard 116*3f982cf4SFabien Sanglard return None 117*3f982cf4SFabien Sanglard 118*3f982cf4SFabien Sanglardif __name__ == "__main__": 119*3f982cf4SFabien Sanglard main() 120