@@ -0,0 +1,2002 @@
+#!/usr/bin/env python3%0A%22%22%22Run meson and ninja to build the ots-sanitize executable from source.%0A%0ANOTE: This script requires Python 3.6 or above. However the generated binary%0Ais independent from the python version used to run it.%0A%22%22%22%0Aimport sys%0Afrom pathlib import Path%0Aimport os%0Aimport subprocess%0Aimport shutil%0Aimport errno%0Aimport argparse%0A%0A%0AROOT = Path(__file__).parent.resolve()%0ABUILD_ROOT = ROOT / %22build%22%0ABUILD_DIR = BUILD_ROOT / %22meson%22%0ASRC_DIR = ROOT.joinpath(%22src%22, %22c%22, %22ots%22)%0A%0ATOOLS = %7B%0A    %22meson%22: os.environ.get(%22MESON_EXE%22, %22meson%22),%0A    %22ninja%22: os.environ.get(%22NINJA_EXE%22, %22ninja%22),%0A%7D%0A%0AMESON_CMD = %5B%0A    TOOLS%5B%22meson%22%5D,%0A    %22--unity=on%22,%0A    %22--buildtype=release%22,%0A    %22--strip%22,%0A    %22-Ddebug=true%22,%0A    BUILD_DIR,%0A    SRC_DIR,%0A%5D%0A%0ANINJA_CMD = %5BTOOLS%5B%22ninja%22%5D, %22-C%22, BUILD_DIR%5D%0A%0A%0Aclass ExecutableNotFound(FileNotFoundError):%0A    def __init__(self, name, path):%0A        msg = f%22%7Bname%7D executable not found: '%7Bpath%7D'%22%0A        super().__init__(errno.ENOENT, msg)%0A%0A%0Adef check_tools():%0A    for name, path in TOOLS.items():%0A        if shutil.which(path) is None:%0A            raise ExecutableNotFound(name, path)%0A%0A%0Adef configure(reconfigure=False):%0A    if not (BUILD_DIR / %22build.ninja%22).exists():%0A        subprocess.run(MESON_CMD, check=True)%0A    elif reconfigure:%0A        subprocess.run(MESON_CMD + %5B%22--reconfigure%22%5D, check=True)%0A%0A%0Adef make(*targets, clean=False):%0A    targets = list(targets)%0A    if clean:%0A        subprocess.run(NINJA_CMD + %5B%22-t%22, %22clean%22%5D + targets, check=True)%0A    subprocess.run(NINJA_CMD + targets, check=True)%0A%0A%0Adef main(args=None):%0A    parser = argparse.ArgumentParser()%0A    parser.add_argument(%22-f%22, %22--force%22, action=%22store_true%22)%0A    parser.add_argument(%22targets%22, nargs=%22*%22)%0A    options = parser.parse_args(args)%0A%0A    check_tools()%0A%0A    try:%0A        configure(reconfigure=options.force)%0A%0A        make(*options.targets, clean=options.force)%0A    except subprocess.CalledProcessError as e:%0A        return e.returncode%0A%0A%0Aif __name__ == %22__main__%22:%0A    sys.exit(main())%0A

add build.py script