diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py index 60de5a1ad561464f9ee20c9ca562698369d7c5cf..8be8bb71f2adefcdcdca784b7b5cd5de674a6df5 100644 --- a/pyopencl/__init__.py +++ b/pyopencl/__init__.py @@ -131,6 +131,8 @@ class Program(object): raise AttributeError("'%s' was not found as a program " "info attribute or as a kernel name" % attr) + # {{{ build + def build(self, options=[], devices=None, cache_dir=None): if isinstance(options, str): options = [options] @@ -146,20 +148,40 @@ class Program(object): self._prg = _cl._Program(self._context, self._source) if self._prg is not None: - self._prg._build(" ".join(options), devices) + # uncached + + self._build_and_catch_errors( + lambda: self._prg.build(" ".join(options), devices), + options=options) + else: - from pyopencl.cache import create_built_program_from_source_cached + # cached - err = None - try: - self._prg = create_built_program_from_source_cached( + from pyopencl.cache import create_built_program_from_source_cached + self._prg = self._build_and_catch_errors( + lambda: create_built_program_from_source_cached( self._context, self._source, options, devices, - cache_dir=cache_dir) - except _cl.RuntimeError, e: - from pytools import Record - class ErrorRecord(Record): - pass + cache_dir=cache_dir), + options=options) + + del self._context + del self._source + + return self + + def _build_and_catch_errors(self, build_func, options): + try: + return build_func() + except _cl.RuntimeError, e: + from pytools import Record + class ErrorRecord(Record): + pass + + what = e.what + if options: + what = what + "\n(options: %s)" % " ".join(options) + if self._source is not None: from tempfile import NamedTemporaryFile srcfile = NamedTemporaryFile(mode="wt", delete=False, suffix=".cl") try: @@ -167,35 +189,30 @@ class Program(object): finally: srcfile.close() - what = e.what - if options: - what = what + "\n(options: %s)" % " ".join(options) what = what + "\n(source saved as %s)" % srcfile.name - code = e.code - routine = e.routine - - err = _cl.RuntimeError( - ErrorRecord( - what=lambda : what, - code=lambda : code, - routine=lambda : routine)) + code = e.code + routine = e.routine - if err is not None: - # Python 3.2 outputs the whole list of currently active exceptions - # This serves to remove one (redundant) level from that nesting. - raise err + err = _cl.RuntimeError( + ErrorRecord( + what=lambda : what, + code=lambda : code, + routine=lambda : routine)) - del self._context - del self._source + # Python 3.2 outputs the whole list of currently active exceptions + # This serves to remove one (redundant) level from that nesting. + raise err - return self + # }}} def compile(self, options=[], devices=None, headers=[]): options = " ".join(options) return self._prg().compile(options, devices, headers) + + def create_program_with_built_in_kernels(context, devices, kernel_names): if not isinstance(kernel_names, str): kernel_names = ":".join(kernel_names)