code: def preprocess_source(source, options, nvcc):
      handle, source_path = mkstemp(suffix=".cu")
  
      outf = open(source_path, "w")
      outf.write(source)
      outf.close()
      os.close(handle)
  
      cmdline = [nvcc, "--preprocess"] + options + [source_path]
      if "win32" in sys.platform:
          cmdline.extend(["--compiler-options", "-EP"])
      else:
          cmdline.extend(["--compiler-options", "-P"])
  
      result, stdout, stderr = call_capture_output(
          cmdline, error_on_nonzero=False
      )
  
      if result != 0:
          from pycuda.driver import CompileError
  
          raise CompileError(
              "nvcc preprocessing of %s failed" % source_path,
              cmdline,
              stderr=stderr,
          )
  
      # sanity check
      if len(stdout) < 0.5 * len(source):
          from pycuda.driver import CompileError
  
          raise CompileError(
              "nvcc preprocessing of %s failed with ridiculously "
              "small code output - likely unsupported compiler."
              % source_path,
              cmdline,
              stderr=stderr.decode("utf-8", "replace"),
          )
  
      unlink(source_path)
  
      preprocessed_str = stdout.decode("utf-8", "replace")
  
      # remove the temporary filename from the preprocessed source code to get reproducible hashes
      return preprocessed_str.replace(os.path.basename(source_path), "")
  
imports: from pytools import memoize
  import os
  import sys
  from tempfile import mkstemp
  from os import unlink
  from pytools.prefork import call_capture_output
label_desc: Use image node_id 3 for calling a global function with example usage: preprocess_source(source, options, nvcc) and returns: preprocessed_str