#!/usr/bin/env python """ Uses the official Khronos-XML specs to generate a GL/GLES/EGL/GLX/WGL Loader made for your needs. Glad currently supports the languages C, D, Nim and Volt. """ from collections import namedtuple import logging import sys from glad.opener import URLOpener from glad.spec import SPECS import glad.lang Version = namedtuple('Version', ['major', 'minor']) logger = logging.getLogger('glad') def main(): import os.path import argparse from argparse import ArgumentParser opener = URLOpener() def get_spec(value): if value not in SPECS: raise argparse.ArgumentTypeError('Unknown specification') spec_cls = SPECS[value] if os.path.exists(value + '.xml'): logger.info('using local specification: \'%s.xml\'', value) return spec_cls.from_file(value + '.xml') logger.info('getting \'%s\' specification from SVN', value) return spec_cls.from_svn(opener=opener) def ext_file(value): msg = 'Invalid extensions argument' if os.path.exists(value): msg = 'Invalid extensions file' try: with open(value, 'r') as f: return f.read().split() except IOError: pass else: return [v.strip() for v in value.split(',') if v] raise argparse.ArgumentTypeError(msg) def version(value): if value is None or len(value.strip()) == 0: return None v = value if '.' not in v: v = '{}.0'.format(v) try: return Version(*map(int, v.split('.'))) except ValueError: pass raise argparse.ArgumentTypeError('Invalid version: "{}"'.format(value)) def cmdapi(value): try: return dict((p[0], version(p[1])) for p in (list(map(str.strip, e.split('='))) for e in filter(bool, map(str.strip, value.split(','))))) except IndexError: pass raise argparse.ArgumentTypeError( 'Invalid api-string: "{}"'.format(value) ) description = __doc__ parser = ArgumentParser(description=description) parser.add_argument('--profile', dest='profile', choices=['core', 'compatibility'], default='compatibility', help='OpenGL profile (defaults to compatibility)') parser.add_argument('--out-path', dest='out', required=True, help='Output path for loader') parser.add_argument('--api', dest='api', type=cmdapi, help='API type/version pairs, like "gl=3.2,gles=", ' 'no version means latest') parser.add_argument('--generator', dest='generator', default='d', choices=['c', 'c-debug', 'd', 'nim', 'volt'], required=True, help='Language to generate the binding for') parser.add_argument('--extensions', dest='extensions', default=None, type=ext_file, help='Path to extensions file or comma separated ' 'list of extensions, if missing ' 'all extensions are included') parser.add_argument('--spec', dest='spec', default='gl', choices=['gl', 'egl', 'glx', 'wgl'], help='Name of the spec') parser.add_argument('--no-loader', dest='no_loader', action='store_true') parser.add_argument('--omit-khrplatform', dest='omit_khrplatform', action='store_true', help='Omits inclusion of the khrplatform.h ' 'file which is often unnecessary. ' 'Only has an effect if used together ' 'with c generators.') parser.add_argument('--local-files', dest='local_files', action='store_true', help='Forces every file directly into the output ' 'directory. No src or include subdirectories ' 'are generated. ' 'Only has an effect if used together ' 'with c generators.') parser.add_argument('--quiet', dest='quiet', action='store_true') ns = parser.parse_args() if not ns.quiet: logging.basicConfig( format='[%(asctime)s][%(levelname)s\t][%(name)-7s\t]: %(message)s', datefmt='%m/%d/%Y %H:%M:%S', level=logging.DEBUG ) spec = get_spec(ns.spec) if spec.NAME == 'gl': spec.profile = ns.profile api = ns.api if api is None or len(api.keys()) == 0: api = {spec.NAME: None} generator_cls, loader_cls = glad.lang.get_generator( ns.generator, spec.NAME.lower() ) if loader_cls is None: return parser.error('API/Spec not yet supported') loader = loader_cls(api, disabled=ns.no_loader, local_files=ns.local_files) logger.info('generating \'%s\' bindings', spec.NAME) with generator_cls( ns.out, spec, api, ns.extensions, loader=loader, opener=opener, local_files=ns.local_files, omit_khrplatform=ns.omit_khrplatform ) as generator: generator.generate() logger.info('generating \'%s\' bindings - done', spec.NAME) if __name__ == '__main__': main()