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)