docs: def get_prebuilt_targets(build_context):
      """Return set of target names that are contained within cached base images
  
      These targets may be considered "pre-built", and skipped during build.
      """
      logger.info('Scanning for cached base images')
      # deps that are part of cached based images
      contained_deps = set()
      # deps that are needed by images that are going to be built,
      # but are not part of their base images
      required_deps = set()
      # mapping from target name to set of all its deps (descendants)
      cached_descendants = CachedDescendants(build_context.target_graph)
  
      for target_name, target in build_context.targets.items():
          if 'image_caching_behavior' not in target.props:
              continue
          image_name = get_image_name(target)
          image_tag = target.props.image_tag
          icb = ImageCachingBehavior(image_name, image_tag,
                                     target.props.image_caching_behavior)
          target.image_id = handle_build_cache(build_context.conf, image_name,
                                               image_tag, icb)
          if target.image_id:
              # mark deps of cached base image as "contained"
              image_deps = cached_descendants.get(target_name)
              contained_deps.update(image_deps)
              contained_deps.add(target.name)
          else:
              # mark deps of image that is going to be built
              # (and are not deps of its base image) as "required"
              image_deps = cached_descendants.get(target_name)
              base_image_deps = cached_descendants.get(target.props.base_image)
              required_deps.update(image_deps - base_image_deps)
      return contained_deps - required_deps