1#!/usr/bin/env python3 2 3import argparse 4import subprocess 5import shutil 6import os 7import sys 8from pathlib import Path 9 10def run(argsv): 11 commands = [[]] 12 SEPARATOR = ';;;' 13 14 # Generate CMD parameters 15 parser = argparse.ArgumentParser(description='Wrapper for add_custom_command') 16 parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to') 17 parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files') 18 parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake') 19 parser.add_argument('commands', nargs=argparse.REMAINDER, help='A "{}" seperated list of commands'.format(SEPARATOR)) 20 21 # Parse 22 args = parser.parse_args(argsv) 23 24 dummy_target = None 25 if len(args.outputs) == 1 and len(args.original_outputs) == 0: 26 dummy_target = args.outputs[0] 27 elif len(args.outputs) != len(args.original_outputs): 28 print('Length of output list and original output list differ') 29 sys.exit(1) 30 31 for i in args.commands: 32 if i == SEPARATOR: 33 commands += [[]] 34 continue 35 36 i = i.replace('"', '') # Remove lefover quotes 37 commands[-1] += [i] 38 39 # Execute 40 for i in commands: 41 # Skip empty lists 42 if not i: 43 continue 44 45 cmd = [] 46 stdout = None 47 stderr = None 48 capture_file = '' 49 50 for j in i: 51 if j in ['>', '>>']: 52 stdout = subprocess.PIPE 53 continue 54 elif j in ['&>', '&>>']: 55 stdout = subprocess.PIPE 56 stderr = subprocess.STDOUT 57 continue 58 59 if stdout is not None or stderr is not None: 60 capture_file += j 61 else: 62 cmd += [j] 63 64 try: 65 os.makedirs(args.directory, exist_ok=True) 66 67 res = subprocess.run(cmd, stdout=stdout, stderr=stderr, cwd=args.directory, check=True) 68 if capture_file: 69 out_file = Path(args.directory) / capture_file 70 out_file.write_bytes(res.stdout) 71 except subprocess.CalledProcessError: 72 sys.exit(1) 73 74 if dummy_target: 75 with open(dummy_target, 'a'): 76 os.utime(dummy_target, None) 77 sys.exit(0) 78 79 # Copy outputs 80 zipped_outputs = zip(args.outputs, args.original_outputs) 81 for expected, generated in zipped_outputs: 82 do_copy = False 83 if not os.path.exists(expected): 84 if not os.path.exists(generated): 85 print('Unable to find generated file. This can cause the build to fail:') 86 print(generated) 87 do_copy = False 88 else: 89 do_copy = True 90 elif os.path.exists(generated): 91 if os.path.getmtime(generated) > os.path.getmtime(expected): 92 do_copy = True 93 94 if do_copy: 95 if os.path.exists(expected): 96 os.remove(expected) 97 shutil.copyfile(generated, expected) 98 99if __name__ == '__main__': 100 sys.run(sys.argv[1:]) 101