summaryrefslogtreecommitdiffstats
path: root/mesonbuild/scripts/cmake_run_ctgt.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/scripts/cmake_run_ctgt.py')
-rwxr-xr-xmesonbuild/scripts/cmake_run_ctgt.py103
1 files changed, 103 insertions, 0 deletions
diff --git a/mesonbuild/scripts/cmake_run_ctgt.py b/mesonbuild/scripts/cmake_run_ctgt.py
new file mode 100755
index 0000000..a788ba5
--- /dev/null
+++ b/mesonbuild/scripts/cmake_run_ctgt.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+from __future__ import annotations
+
+import argparse
+import subprocess
+import shutil
+import sys
+from pathlib import Path
+import typing as T
+
+def run(argsv: T.List[str]) -> int:
+ commands = [[]] # type: T.List[T.List[str]]
+ SEPARATOR = ';;;'
+
+ # Generate CMD parameters
+ parser = argparse.ArgumentParser(description='Wrapper for add_custom_command')
+ parser.add_argument('-d', '--directory', type=str, metavar='D', required=True, help='Working directory to cwd to')
+ parser.add_argument('-o', '--outputs', nargs='+', metavar='O', required=True, help='Expected output files')
+ parser.add_argument('-O', '--original-outputs', nargs='*', metavar='O', default=[], help='Output files expected by CMake')
+ parser.add_argument('commands', nargs=argparse.REMAINDER, help=f'A "{SEPARATOR}" separated list of commands')
+
+ # Parse
+ args = parser.parse_args(argsv)
+ directory = Path(args.directory)
+
+ dummy_target = None
+ if len(args.outputs) == 1 and len(args.original_outputs) == 0:
+ dummy_target = Path(args.outputs[0])
+ elif len(args.outputs) != len(args.original_outputs):
+ print('Length of output list and original output list differ')
+ return 1
+
+ for i in args.commands:
+ if i == SEPARATOR:
+ commands += [[]]
+ continue
+
+ i = i.replace('"', '') # Remove lefover quotes
+ commands[-1] += [i]
+
+ # Execute
+ for i in commands:
+ # Skip empty lists
+ if not i:
+ continue
+
+ cmd = []
+ stdout = None
+ stderr = None
+ capture_file = ''
+
+ for j in i:
+ if j in {'>', '>>'}:
+ stdout = subprocess.PIPE
+ continue
+ elif j in {'&>', '&>>'}:
+ stdout = subprocess.PIPE
+ stderr = subprocess.STDOUT
+ continue
+
+ if stdout is not None or stderr is not None:
+ capture_file += j
+ else:
+ cmd += [j]
+
+ try:
+ directory.mkdir(parents=True, exist_ok=True)
+
+ res = subprocess.run(cmd, stdout=stdout, stderr=stderr, cwd=str(directory), check=True)
+ if capture_file:
+ out_file = directory / capture_file
+ out_file.write_bytes(res.stdout)
+ except subprocess.CalledProcessError:
+ return 1
+
+ if dummy_target:
+ dummy_target.touch()
+ return 0
+
+ # Copy outputs
+ zipped_outputs = zip([Path(x) for x in args.outputs], [Path(x) for x in args.original_outputs])
+ for expected, generated in zipped_outputs:
+ do_copy = False
+ if not expected.exists():
+ if not generated.exists():
+ print('Unable to find generated file. This can cause the build to fail:')
+ print(generated)
+ do_copy = False
+ else:
+ do_copy = True
+ elif generated.exists():
+ if generated.stat().st_mtime > expected.stat().st_mtime:
+ do_copy = True
+
+ if do_copy:
+ if expected.exists():
+ expected.unlink()
+ shutil.copyfile(str(generated), str(expected))
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(run(sys.argv[1:]))