Esempio n. 1
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Update build defintions to include all GLSL files.',
        prog=args[0])
    add_common_args(parser)
    update(parser.parse_args(args[1:]))
Esempio n. 2
0
def main(args):
    parser = argparse.ArgumentParser(
        description='Generate an ZIP distribution.', prog=args[0])

    parser.add_argument(
        'build_dir',
        help='The build directory (defaults to CWD)',
        default=Path(os.getcwd()),
        type=Path,
        nargs='?',
    )

    parser.add_argument(
        'output',
        help='The output file path',
        type=Path,
    )

    add_common_args(parser)
    args = parser.parse_args(args[1:])

    with temp_install(args.build_dir) as install_dir, ZipFile(
            str(args.output), "w", ZIP_DEFLATED) as zfile:
        for path in install_dir.glob('**/*'):
            if not path.is_dir():
                rel = str(path.relative_to(install_dir))
                print("Adding file {}".format(rel))
                zfile.write(str(path), rel)

    print("Generated package {}".format(str(args.output)))
Esempio n. 3
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Perform all automated routine maintenance tasks.',
        prog=args[0])
    add_common_args(parser)
    pargs = parser.parse_args(args[1:])

    scripts = pargs.rootdir / 'scripts' / 'upkeep'

    tasks = (
        ['fixup-source-files', 'check-rng-usage'],
        'update-glsl-sources',
    )

    with ThreadPoolExecutor() as ex:

        def do_task(task):
            if isinstance(task, str):
                print('[upkeep] begin task', task)
                subprocess.check_call([scripts / f'{task}.py'] + args[1:])
                print('[upkeep] task', task, 'done')
            else:
                for t in task:
                    do_task(t)

        tuple(ex.map(do_task, tasks))
Esempio n. 4
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(description='Update build defintions to include all GLSL files.', prog=args[0])
    add_common_args(parser)

    args = parser.parse_args(args[1:])

    for shaders_root in (args.rootdir / 'resources').glob('*/shader'):
        update(args, shaders_root)
Esempio n. 5
0
def main(args):
    parser = argparse.ArgumentParser(description='Generate an NSIS installer for Windows.', prog=args[0])

    parser.add_argument('build_dir',
        help='The build directory (defaults to CWD)',
        default=Path(os.getcwd()),
        type=Path,
        nargs='?',
    )

    parser.add_argument('script_template',
        help='The NSIS script template',
        type=Path,
    )

    add_configure_args(parser)
    add_common_args(parser)

    args = parser.parse_args(args[1:])
    args.variables = dict(args.variables)

    with args.script_template.open('r') as infile:
        template = infile.read()

    with temp_install(args.build_dir) as install_dir:
        glob  = tuple(install_dir.glob('**/*'))
        files = sorted((PureWindowsPath(p.relative_to(install_dir)) for p in glob if not p.is_dir()), reverse=True)
        dirs  = sorted((PureWindowsPath(p.relative_to(install_dir)) for p in glob if     p.is_dir()), reverse=True)

        indent = ' ' * 4
        instdir = '$INSTDIR'

        uninstall_files = ('\n'+indent).join('Delete "{}\\{}"'.format(instdir, path) for path in files)
        uninstall_dirs  = ('\n'+indent).join('RMDir "{}\\{}"'.format(instdir, path) for path in dirs)
        uninstall_commands = indent + ('\n\n'+indent).join((uninstall_files, uninstall_dirs))

        print(uninstall_commands)

        args.variables.update({
            'INSTALL_DIR': str(install_dir),
            'UNINSTALL_COMMANDS': uninstall_commands,
            'INSTALL_OPTIONS_INI': str(Path(args.rootdir) / 'scripts' / 'NSIS.InstallOptions.ini')
        })

        script = configure(template, args.variables,
            prefix='@',
            suffix='@',
            args=args
        )

        nsis_cmd = shlex.split('makensis -V3 -NOCD -INPUTCHARSET UTF8 -WX -')

        with subprocess.Popen(nsis_cmd, stdin=subprocess.PIPE, cwd=str(args.build_dir)) as proc:
            proc.stdin.write(script.encode('utf-8'))

        if proc.returncode != 0:
            raise MakeNSISError(proc.returncode)
Esempio n. 6
0
def main(args):
    import logging
    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger(__name__)

    parser = argparse.ArgumentParser(description='Generate a distribution archive.', prog=args[0])

    parser.add_argument('build_dir',
        help='the build directory (defaults to CWD)',
        default=Path(os.getcwd()),
        type=Path,
        nargs='?',
    )

    parser.add_argument('output',
        help='the output file path',
        type=Path,
    )

    parser.add_argument('--format',
        help='the archive format',
        default='zip',
        choices=sorted(map(lambda x: x[0], shutil.get_archive_formats())),
    )

    parser.add_argument('--prefix',
        help='add a common prefix to all files and directories in the archive',
        default=None,
    )

    add_common_args(parser)
    args = parser.parse_args(args[1:])

    if args.prefix is not None:
        p = PurePosixPath(args.prefix)

        if p.is_absolute() or p.is_reserved() or '..' in p.parts:
            raise ValueError('Bad prefix: {}'.format(args.prefix))

        args.prefix = str(p)

        if args.prefix == '.':
            args.prefix = None

    with temp_install(args.build_dir) as install_dir:
        if args.prefix is not None:
            os.chdir(str(install_dir.parent))
            install_dir.rename(install_dir.parent / args.prefix)
            archive = shutil.make_archive(str(args.output), args.format, '.', str(args.prefix))
        else:
            archive = shutil.make_archive(str(args.output), args.format, str(install_dir))

        archive = Path(archive)
        archive.rename(args.output)

    print("Generated distribution archive {}".format(str(args.output)))
Esempio n. 7
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(description='Fix-up all C sources and headers - add/update copyright header, include guards, etc.', prog=args[0])
    add_common_args(parser)
    pargs = parser.parse_args(args[1:])

    j = Janitor(pargs.rootdir / 'src')

    with ThreadPoolExecutor() as ex:
        tuple(ex.map(j.do_maintenance, j.iter_files()))
Esempio n. 8
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Update build defintions to include all GLSL files.',
        prog=args[0])
    add_common_args(parser)

    args = parser.parse_args(args[1:])

    for shaders_root in (args.rootdir / 'resources').glob('*/shader'):
        update(args, shaders_root)
Esempio n. 9
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description=
        'Fix-up all C sources and headers - add/update copyright header, include guards, etc.',
        prog=args[0])
    add_common_args(parser)
    pargs = parser.parse_args(args[1:])

    j = Janitor(pargs.rootdir / 'src')

    with ThreadPoolExecutor() as ex:
        tuple(ex.map(j.do_maintenance, j.iter_files()))
Esempio n. 10
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(description='Perform all automated routine maintenance tasks.', prog=args[0])
    add_common_args(parser)
    pargs = parser.parse_args(args[1:])

    scripts = pargs.rootdir / 'scripts' / 'upkeep'

    tasks = (
        'fixup-source-files',
        'update-glsl-sources',
    )

    with ThreadPoolExecutor() as ex:
        tuple(ex.map(lambda task: subprocess.check_call([scripts / f'{task}.py'] + args[1:]), tasks))
Esempio n. 11
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(description='Package game assets.',
                                     prog=args[0])

    parser.add_argument('directory',
                        type=DirPathType,
                        help='the source package directory')

    parser.add_argument('output', type=Path, help='the output archive path')

    add_common_args(parser, depfile=True)

    args = parser.parse_args(args[1:])
    pack(args)
Esempio n. 12
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Update build defintions to include all GLSL files.',
        prog=args[0])
    add_common_args(parser)

    args = parser.parse_args(args[1:])

    with (args.builddir / 'compile_commands.json').open() as f:
        compile_commands = json.load(f)

    with ThreadPoolExecutor() as ex:
        tuple(
            ex.map(lambda c: find_suspicious_callsites(preprocess(c)),
                   compile_commands))
Esempio n. 13
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Check source code for suspicious RNG API usage.',
        prog=args[0])
    add_common_args(parser)

    args = parser.parse_args(args[1:])

    with (args.builddir / 'compile_commands.json').open() as f:
        compile_commands = json.load(f)

    with ThreadPoolExecutor() as ex:
        tuple(
            ex.map(lambda c: find_suspicious_callsites(preprocess(c)),
                   compile_commands))
Esempio n. 14
0
def main(args):
    parser = argparse.ArgumentParser(
        description='Generate a reusable gaussian blur shader.', prog=args[0])

    def kernsize(v):
        v = int(v)
        if not v & 1:
            raise ValueError('Kernel size must be an odd integer')
        return v

    parser.add_argument(
        'kernel_size',
        help='size of the 1D convolution kernel, must be odd',
        type=kernsize,
    )

    parser.add_argument(
        'sigma',
        help='standard deviation value for the probability density function',
        type=float,
    )

    parser.add_argument(
        'name',
        help=
        'name of the shader, defaults to blurX, where X is the kernel size',
        type=str,
        default=None,
        nargs='?',
    )

    add_common_args(parser)
    args = parser.parse_args()

    if args.name is None:
        args.name = f'blur{args.kernel_size}'

    shaders = args.rootdir / 'resources' / 'shader'
    blurs = shaders / 'lib' / 'blur'
    blurs.mkdir(parents=True, exist_ok=True)

    update_text_file(blurs / f'{args.name}.glslh', gen_lib_shader(args))
    update_text_file(shaders / f'{args.name}.frag.glsl',
                     gen_fragment_shader(args))
    update_text_file(shaders / f'{args.name}.prog', gen_meta(args))
Esempio n. 15
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(description='Package game assets.', prog=args[0])

    parser.add_argument('directory',
        type=DirPathType,
        help='the source package directory'
    )

    parser.add_argument('output',
        type=Path,
        help='the output archive path'
    )

    add_common_args(parser, depfile=True)

    args = parser.parse_args(args[1:])
    pack(args)
Esempio n. 16
0
def main(args):
    import argparse
    parser = argparse.ArgumentParser(
        description='Perform all automated routine maintenance tasks.',
        prog=args[0])
    add_common_args(parser)
    pargs = parser.parse_args(args[1:])

    scripts = pargs.rootdir / 'scripts' / 'upkeep'

    tasks = (
        'fixup-source-files',
        'update-glsl-sources',
    )

    with ThreadPoolExecutor() as ex:
        tuple(
            ex.map(
                lambda task: subprocess.check_call([scripts / f'{task}.py'] +
                                                   args[1:]), tasks))
Esempio n. 17
0
def main(args):
    parser = argparse.ArgumentParser(description='Generate a reusable gaussian blur shader.', prog=args[0])

    def kernsize(v):
        v = int(v)
        if not v & 1:
            raise ValueError('Kernel size must be an odd integer')
        return v

    parser.add_argument('kernel_size',
        help='size of the 1D convolution kernel, must be odd',
        type=kernsize,
    )

    parser.add_argument('sigma',
        help='standard deviation value for the probability density function',
        type=float,
    )

    parser.add_argument('name',
        help='name of the shader, defaults to blurX, where X is the kernel size',
        type=str,
        default=None,
        nargs='?',
    )

    add_common_args(parser)
    args = parser.parse_args()

    if args.name is None:
        args.name = f'blur{args.kernel_size}'

    shaders = args.rootdir / 'resources' / 'shader'
    blurs = shaders / 'lib' / 'blur'
    blurs.mkdir(parents=True, exist_ok=True)

    update_text_file(blurs / f'{args.name}.glslh', gen_lib_shader(args))
    update_text_file(shaders / f'{args.name}.frag.glsl', gen_fragment_shader(args))
    update_text_file(shaders / f'{args.name}.prog', gen_meta(args))
Esempio n. 18
0
def main(args):
    parser = argparse.ArgumentParser(
        description='Generate an NSIS installer for Windows.', prog=args[0])

    parser.add_argument(
        'build_dir',
        help='The build directory (defaults to CWD)',
        default=Path(os.getcwd()),
        type=Path,
        nargs='?',
    )

    parser.add_argument(
        'script_template',
        help='The NSIS script template',
        type=Path,
    )

    add_configure_args(parser)
    add_common_args(parser)

    args = parser.parse_args(args[1:])
    args.variables = dict(args.variables)

    with args.script_template.open('r') as infile:
        template = infile.read()

    with temp_install(args.build_dir) as install_dir:
        glob = tuple(install_dir.glob('**/*'))
        files = sorted((PureWindowsPath(p.relative_to(install_dir))
                        for p in glob if not p.is_dir()),
                       reverse=True)
        dirs = sorted((PureWindowsPath(p.relative_to(install_dir))
                       for p in glob if p.is_dir()),
                      reverse=True)

        indent = ' ' * 4
        instdir = '$INSTDIR'

        uninstall_files = ('\n' + indent).join(
            'Delete "{}\\{}"'.format(instdir, path) for path in files)
        uninstall_dirs = ('\n' + indent).join(
            'RMDir "{}\\{}"'.format(instdir, path) for path in dirs)
        uninstall_commands = ('\n\n' + indent).join(
            (uninstall_files, uninstall_dirs))

        print(uninstall_commands)

        args.variables.update({
            'INSTALL_DIR':
            str(install_dir),
            'UNINSTALL_COMMANDS':
            uninstall_commands,
            'INSTALL_OPTIONS_INI':
            str(Path(args.rootdir) / 'scripts' / 'NSIS.InstallOptions.ini')
        })

        script = configure(template,
                           args.variables,
                           prefix='@',
                           suffix='@',
                           args=args)

        nsis_cmd = shlex.split('makensis -V4 -NOCD -INPUTCHARSET UTF8 -WX -')

        with subprocess.Popen(nsis_cmd,
                              stdin=subprocess.PIPE,
                              cwd=str(args.build_dir)) as proc:
            proc.stdin.write(script.encode('utf-8'))

        if proc.returncode != 0:
            raise MakeNSISError(proc.returncode)
Esempio n. 19
0
def main(args):
    parser = argparse.ArgumentParser(description='Regenerate a Meson build directory, attempting to preserve build options.', prog=args[0])

    parser.add_argument('build_dir',
        default=Path.cwd(),
        type=Path,
        nargs='?',
        help='the build directory (defaults to CWD)',
    )

    parser.add_argument('dest_build_dir',
        default=None,
        type=Path,
        nargs='?',
        help='the destination directory (defaults to same as build_dir)',
    )

    parser.add_argument('--meson',
        default=['meson'],
        type=shlex.split,
        help='override the Meson executable (useful for wrappers)',
    )

    parser.add_argument('meson_args',
        default=[],
        nargs='*',
        help='additional arguments for Meson',
    )

    add_common_args(parser)
    args = parser.parse_args(args[1:])

    if args.dest_build_dir is None:
        args.dest_build_dir = args.build_dir

    with in_dir(args.build_dir):
        try:
            build_options = meson_introspect('--buildoptions')
        except subprocess.SubprocessError:
            print("Warning: meson introspect failed, retrieving options from saved_options.json. This may not be up to date.", file=sys.stderr)

            with open('saved_options.json') as infile:
                build_options = json.loads(infile.read())

    regen_cmdline = args.meson + [
        str(args.rootdir.resolve(strict=True)),
        str(args.dest_build_dir.resolve(strict=False)),
    ]

    meson_options = set(re.findall(r'\[--([\w-]+)\s+.*?\]', subprocess.check_output(args.meson + ['--help']).decode('utf8'), re.A))

    def opt_str_value(opt, value):
        if isinstance(value, bool):
            # Meson <= 0.43.0 bug
            return str(value).lower()

        if opt == 'install_umask':
            return '%04o' % int(value)

        return str(value)

    for opt in build_options:
        name = opt['name']
        value = opt_str_value(name, opt['value'])

        if name in meson_options:
            regen_cmdline.append('--{}={}'.format(name, value))

    regen_cmdline += args.meson_args

    args.dest_build_dir.mkdir(parents=True, exist_ok=True)

    with in_dir(args.dest_build_dir):
        obj = {
            'command': regen_cmdline,
            'build_options': build_options,
        }

        with Path('imported_options.json').open('w') as outfile:
            json.dump(obj, outfile,
                ensure_ascii=False,
                indent=4,
                sort_keys=True,
            )

        meson_dir = Path('meson-private')
        meson_dir_bak = meson_dir.with_name(meson_dir.name + '.bak')

        if meson_dir.is_dir():
            shutil.rmtree(meson_dir_bak, ignore_errors=True)
            meson_dir.rename(meson_dir_bak)

        print('+', regen_cmdline)
        subprocess.check_call(regen_cmdline)

        for opt in build_options:
            name = opt['name']
            value = opt_str_value(name, opt['value'])
            cmdline = args.meson + ['configure', '-D{}={}'.format(name, value)]
            print('+', cmdline)
            subprocess.call(cmdline)

    print('')
    print("Regeneration done. This process is not 100% reliable; you may want to check the output of 'meson configure'")
Esempio n. 20
0
def main(args):
    parser = argparse.ArgumentParser(
        description=
        'Regenerate a Meson build directory, attempting to preserve build options.',
        prog=args[0])

    parser.add_argument(
        'build_dir',
        default=Path.cwd(),
        type=Path,
        nargs='?',
        help='the build directory (defaults to CWD)',
    )

    parser.add_argument(
        'dest_build_dir',
        default=None,
        type=Path,
        nargs='?',
        help='the destination directory (defaults to same as build_dir)',
    )

    parser.add_argument(
        '--meson',
        default=['meson'],
        type=shlex.split,
        help='override the Meson executable (useful for wrappers)',
    )

    parser.add_argument(
        'meson_args',
        default=[],
        nargs='*',
        help='additional arguments for Meson',
    )

    add_common_args(parser)
    args = parser.parse_args(args[1:])

    if args.dest_build_dir is None:
        args.dest_build_dir = args.build_dir

    with in_dir(args.build_dir):
        try:
            build_options = meson_introspect('--buildoptions')
        except subprocess.SubprocessError:
            print(
                "Warning: meson introspect failed, retrieving options from saved_options.json. This may not be up to date.",
                file=sys.stderr)

            with open('saved_options.json') as infile:
                build_options = json.loads(infile.read())

    regen_cmdline = args.meson + [
        str(args.rootdir.resolve(strict=True)),
        str(args.dest_build_dir.resolve(strict=False)),
    ]

    meson_options = set(
        re.findall(
            r'\[--([\w-]+)\s+.*?\]',
            subprocess.check_output(args.meson + ['--help']).decode('utf8'),
            re.A))

    def opt_str_value(opt, value):
        if isinstance(value, bool):
            # Meson <= 0.43.0 bug
            return str(value).lower()

        if opt == 'install_umask':
            return '%04o' % int(value)

        return str(value)

    for opt in build_options:
        name = opt['name']
        value = opt_str_value(name, opt['value'])

        if name in meson_options:
            regen_cmdline.append('--{}={}'.format(name, value))

    regen_cmdline += args.meson_args

    args.dest_build_dir.mkdir(parents=True, exist_ok=True)

    with in_dir(args.dest_build_dir):
        obj = {
            'command': regen_cmdline,
            'build_options': build_options,
        }

        with Path('imported_options.json').open('w') as outfile:
            json.dump(
                obj,
                outfile,
                ensure_ascii=False,
                indent=4,
                sort_keys=True,
            )

        meson_dir = Path('meson-private')
        meson_dir_bak = meson_dir.with_name(meson_dir.name + '.bak')

        if meson_dir.is_dir():
            shutil.rmtree(meson_dir_bak, ignore_errors=True)
            meson_dir.rename(meson_dir_bak)

        print('+', regen_cmdline)
        subprocess.check_call(regen_cmdline)

        for opt in build_options:
            name = opt['name']
            value = opt_str_value(name, opt['value'])
            cmdline = args.meson + ['configure', '-D{}={}'.format(name, value)]
            print('+', cmdline)
            subprocess.call(cmdline)

    print('')
    print(
        "Regeneration done. This process is not 100% reliable; you may want to check the output of 'meson configure'"
    )