The Meson Build System
http://mesonbuild.com/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.2 KiB
103 lines
3.2 KiB
#!/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:]))
|
|
|