code: def build(self, options=None, devices=None, cache_dir=None):
      options_bytes, include_path = self._process_build_options(
          self._context, options
      )
  
      if cache_dir is None:
          cache_dir = getattr(self._context, "cache_dir", None)
  
      build_descr = None
      if _PYOPENCL_NO_CACHE and self._prg is None:
          build_descr = "uncached source build (cache disabled by user)"
          self._prg = _cl._Program(self._context, self._source)
  
      from time import time
  
      start_time = time()
      was_cached = False
  
      if self._prg is not None:
          # uncached
  
          if build_descr is None:
              build_descr = "uncached source build"
  
          self._build_and_catch_errors(
              lambda: self._prg.build(options_bytes, devices),
              options_bytes=options_bytes,
          )
  
      else:
          # cached
  
          from pyopencl.cache import (
              create_built_program_from_source_cached,
          )
  
          self._prg, was_cached = self._build_and_catch_errors(
              lambda: create_built_program_from_source_cached(
                  self._context,
                  self._source,
                  options_bytes,
                  devices,
                  cache_dir=cache_dir,
                  include_path=include_path,
              ),
              options_bytes=options_bytes,
              source=self._source,
          )
  
          if was_cached:
              build_descr = "cache retrieval"
          else:
              build_descr = (
                  "source build resulting from a binary cache miss"
              )
  
          del self._context
  
      end_time = time()
  
      self._build_duration_info = (
          build_descr,
          was_cached,
          end_time - start_time,
      )
  
      return self
  
imports: from sys import intern
  from warnings import warn
  from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
  from pyopencl.version import VERSION, VERSION_STATUS, VERSION_TEXT
  import pyopencl.cltypes
  import logging
  import os
  import numpy
  import sys
  from pyopencl._cl import get_cl_header_version, program_kind, status_code, platform_info, device_type, device_info, device_topology_type_amd, device_fp_config, device_mem_cache_type, device_local_mem_type, device_exec_capabilities, device_svm_capabilities, command_queue_properties, context_info, gl_context_info, context_properties, command_queue_info, queue_properties, mem_flags, svm_mem_flags, channel_order, channel_type, mem_object_type, mem_info, image_info, pipe_info, pipe_properties, addressing_mode, filter_mode, sampler_info, sampler_properties, map_flags, program_info, program_build_info, program_binary_type, kernel_info, kernel_arg_info, kernel_arg_address_qualifier, kernel_arg_access_qualifier, kernel_arg_type_qualifier, kernel_work_group_info, kernel_sub_group_info, event_info, command_type, command_execution_status, profiling_info, mem_migration_flags, device_partition_property, device_affinity_domain, device_atomic_capabilities, device_device_enqueue_capabilities, version_bits, khronos_vendor_id, Error, MemoryError, LogicError, RuntimeError, Platform, get_platforms, Device, Context, CommandQueue, LocalMemory, MemoryObjectHolder, MemoryObject, MemoryMap, Buffer, _Program, Kernel, Event, wait_for_events, NannyEvent, enqueue_nd_range_kernel, _enqueue_marker, _enqueue_read_buffer, _enqueue_write_buffer, _enqueue_copy_buffer, _enqueue_read_buffer_rect, _enqueue_write_buffer_rect, _enqueue_copy_buffer_rect, _enqueue_read_image, _enqueue_copy_image, _enqueue_write_image, _enqueue_copy_image_to_buffer, _enqueue_copy_buffer_to_image, have_gl, ImageFormat, get_supported_image_formats, Image, Sampler, Pipe
  import inspect
label_desc: Use image node_id 10 for calling the Program obj's underlying member method code with example usage: obj.build(options, devices, cache_dir) and returns: self